题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
提示:
1 <= nums.length <= 104-231 <= nums[i] <= 231 - 1
题解
双指针
/**
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
var moveZeroes = function (nums) {
let j = 0;
for (let i = 0; i < nums.length; i++) {
if (nums[i] !== 0) {
if (i !== j) {
nums[j] = nums[i];
nums[i] = 0;
}
j++;
}
}
};
本题我们采用双指针进行求解
设置i,j两个指针,i指针用于for循环中跟踪数组元素,寻找非零的元素,j指针指向下一个非0元素应该放置的位置
算法通过一次遍历,两重判断实现
- 遇到非零元素 (
nums[i] !== 0)
-
如果
i = j: 元素已经在正确位置(前面没有零),j递增,i递增。 -
如果
i > j: 找到一个非零元素需要向前移动。- 赋值: 将
nums[i]复制到nums[j]的位置(完成了元素的移动)。 - 归零: 将
nums[i]的原位置设为0(为数组末尾准备 0)。 j递增: 非零序列长度增加,j向前移动一位。
- 赋值: 将
- 遇到零元素 (
nums[i] === 0)
j保持不动。i继续向前。- 这使得
j停留在当前 0 的位置,而i继续前进寻找第一个非零元素来覆盖它。
时间、空间复杂度
时间复杂度:O(N)
快指针 i 只遍历数组一次。尽管有 if 语句和赋值操作,但总的操作次数与数组长度 N 成线性关系。
空间复杂度:O(1)
算法只使用了固定数量的额外变量(i 和 j),没有创建新数组,因此是原地操作。