题目来源:LeetCode283:移动零
问题抽象: 给定一个整数数组 nums,要求在不使用额外数组的前提下,原地移动所有零元素至数组末尾,同时保持非零元素的原始相对顺序,需满足以下核心需求:
-
移动规则定义:
- 非零元素稳定性:所有非零元素必须 保持原有顺序(相邻非零元素的前后关系不变);
- 零元素位置约束:所有零必须被移动到所有非零元素 之后(零元素间的相对顺序可任意)。
-
操作约束:
- 原地修改:禁止创建新数组(空间复杂度 O(1));
- 最小化操作次数:元素赋值操作尽可能少(时间复杂度 O(n))。
-
边界处理:
- 空数组或无零元素:直接返回原数组;
- 全零数组:保持全零状态;
- 连续零序列:移动后形成连续零段(如
[1,0,0,3]→[1,3,0,0])。
-
输出要求:
- 无返回值,需直接 修改输入数组
nums; - 示例:
- 输入
[0,1,0,3,12]→ 修改为[1,3,12,0,0]; - 输入
[0]→ 保持[0]。
- 输入
- 无返回值,需直接 修改输入数组
输入:整数数组 nums(长度 ≥ 0)
输出:无(原地修改 nums)。
解题思路
使用双指针技巧,通过一次遍历完成操作:
- 指针定义:
index:指向下一个非零元素应放置的位置(慢指针)。i:遍历数组的指针(快指针)。
- 核心操作:
- 遍历数组,当遇到非零元素时,将其移动到
index指向的位置(若i != index才移动,避免自我赋值),然后index右移。
- 遍历数组,当遇到非零元素时,将其移动到
- 后续处理:
- 遍历结束后,从
index开始到数组末尾的所有位置填充0。
- 遍历结束后,从
亮点:
- 避免自我赋值:当非零元素已在正确位置时(即
i == index),跳过赋值操作,减少不必要的内存写入。 - 最小化赋值次数:仅需
n次赋值(n为数组长度),优于交换法(需3k次赋值,k为非零元素数)。
代码实现(Java版)🔥点击下载源码
class Solution {
public void moveZeroes(int[] nums) {
int index = 0; // 慢指针:指向下一个非零元素应放置的位置
// 第一次遍历:移动所有非零元素到数组前部
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
// 避免自我赋值(当元素已在正确位置时跳过)
if (i != index) {
nums[index] = nums[i];
}
index++; // 慢指针右移
}
}
// 第二次遍历:将剩余位置填充0
for (int i = index; i < nums.length; i++) {
nums[i] = 0;
}
}
}
代码说明
- 双指针逻辑:
- 快指针
i:顺序遍历数组,检查每个元素。 - 慢指针
index:记录非零元素应插入的位置,确保相对顺序。
- 快指针
- 避免自我赋值:
- 当
i == index时,非零元素已在目标位置,无需赋值,直接移动指针。
- 当
- 填充零:
- 遍历结束后,
index后的所有位置用0填充。
- 遍历结束后,
- 效率优化:
- 总赋值次数 = 非零元素数(移动部分) + 零的数量(填充部分) =
n(数组长度),达到理论最小值。
- 总赋值次数 = 非零元素数(移动部分) + 零的数量(填充部分) =
提交详情(执行用时、内存消耗)

8825

被折叠的 条评论
为什么被折叠?



