欢迎光临
我们一直在努力

hot 100 第四题 4. 移动零

题目:

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

核心思路:双指针覆盖法

关键洞察 💡

把问题拆解成两步:

  • 把所有非零元素按顺序"挤"到前面
  • 把后面剩余的位置全部填 0
  • 不需要交换,直接覆盖!

    思维模型

    想象你在整理书架:

    <span style="color:#abb2bf"><code>原始书架:[空, 书A, 空, 书B, 书C]

    步骤1:把所有书依次往前移
    发现 书A → 放到位置0
    发现 书B → 放到位置1
    发现 书C → 放到位置2

    中间状态:[书A, 书B, 书C, 书B, 书C]
    ↑ 后面还有旧数据

    步骤2:把后面的位置清空
    位置3 → 空
    位置4 → 空

    最终书架:[书A, 书B, 书C, 空, 空] ✅</code></span>

    双指针的含义

    java

    <span style="color:#abb2bf"><code class="language-java"><span style="color:#c678dd">int</span> slow <span style="color:#61afef">=</span> <span style="color:#d19a66">0</span><span style="color:#abb2bf">;</span> <span style="color:#5c6370"><em>// "慢指针" – 下一个非零元素应该放的位置</em></span>
    <span style="color:#c678dd">int</span> fast <span style="color:#61afef">=</span> <span style="color:#d19a66">0</span><span style="color:#abb2bf">;</span> <span style="color:#5c6370"><em>// "快指针" – 遍历数组的指针</em></span></code></span>

    指针职责

    指针作用移动规则
    slow 标记"非零区域"的边界 只在放入非零元素后移动
    fast 遍历查找非零元素 每次循环都移动

    详细执行过程

    输入:[0, 1, 0, 3, 12]

    第一阶段:收集非零元素

    <span style="color:#abb2bf"><code>初始状态:
    数组:[0, 1, 0, 3, 12]

    slow=0
    fast=0

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Step 1: fast=0
    nums[0]=0 → 是零,跳过
    slow 不动

    数组:[0, 1, 0, 3, 12]

    slow=0

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Step 2: fast=1
    nums[1]=1 → 非零!
    执行:nums[slow] = nums[fast]
    nums[0] = 1
    slow++

    数组:[1, 1, 0, 3, 12]

    slow=1

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Step 3: fast=2
    nums[2]=0 → 是零,跳过
    slow 不动

    数组:[1, 1, 0, 3, 12]

    slow=1

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Step 4: fast=3
    nums[3]=3 → 非零!
    执行:nums[slow] = nums[fast]
    nums[1] = 3
    slow++

    数组:[1, 3, 0, 3, 12]

    slow=2

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Step 5: fast=4
    nums[4]=12 → 非零!
    执行:nums[slow] = nums[fast]
    nums[2] = 12
    slow++

    数组:[1, 3, 12, 3, 12]

    slow=3

    第一阶段结束!
    非零元素已收集完毕,slow=3 表示后面需要填零</code></span>

    第二阶段:填充零

    <span style="color:#abb2bf"><code>从 slow=3 开始,到数组末尾全部填 0

    i=3: nums[3]=0
    数组:[1, 3, 12, 0, 12]

    i=4: nums[4]=0
    数组:[1, 3, 12, 0, 0]

    完成!✅</code></span>

    题解

    class Solution {
    public void moveZeroes(int[] nums) {
    int slow = 0; // 指向下一个非零元素应该放的位置

    // 步骤1:将所有非零元素依次移到前面
    for (int fast = 0; fast < nums.length; fast++) {
    if (nums[fast] != 0) {
    nums[slow] = nums[fast];
    slow++;
    }
    }

    // 步骤2:将剩余位置填充为 0
    for (int i = slow; i < nums.length; i++) {
    nums[i] = 0;
    }
    }
    }
    ```

    **演示过程**:
    ```
    输入:[0, 1, 0, 3, 12]

    步骤1:移动非零元素
    fast=0, nums[0]=0 → 跳过,slow=0
    fast=1, nums[1]=1 → nums[0]=1, slow=1
    fast=2, nums[2]=0 → 跳过,slow=1
    fast=3, nums[3]=3 → nums[1]=3, slow=2
    fast=4, nums[4]=12 → nums[2]=12, slow=3

    数组变为:[1, 3, 12, 3, 12]
    slow=3 ↑

    步骤2:填充零
    i=3: nums[3]=0
    i=4: nums[4]=0

    最终:[1, 3, 12, 0, 0] ✅

    赞(0)
    未经允许不得转载:171主机测评 » hot 100 第四题 4. 移动零
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址