概要: 给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例:
1 2 3 4 5
| 输入:nums = [0,1,0,3,12] 输出:[1,3,12,0,0]
输入:nums = [0] 输出:[0]
|
提示:
- 1 <= nums.length <= 104
- -231 <= nums[i] <= 231 - 1
心路历程
向后查找法
题目规定了不能复制数组,要原地进行操作,所以得用双指针。我开始想的是,一个指针找0,一个指针找不为0的,找到了就交换。然后开始尝试着写代码,结果发现执行栈溢出了,原来是我将while循环条件写成了不等于0,就导致在超过了原本数组的长度后,得到的值:undefined也能进入循环,然后形成了死循环。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var moveZeroes = function (nums) { if (nums.length === 0 || nums.length === 1) { return nums; } let i = 0; for (let j = 0; j < nums.length; j++) { if (nums[j] === 0 && j !== nums.length - 1) { i = j + 1; while (nums[i] !== undefined && (i < nums.length || nums[i] !== 0)) { if (nums[i] !== 0) { const temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; break; } i++; } } } return nums; };
|
上面的判断条件有些多余,改善一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var moveZeroes = function (nums) { if (nums.length === 0 || nums.length === 1) { return nums; } let i = 0; for (let j = 0; j < nums.length; j++) { if (nums[j] === 0 && j !== nums.length - 1) { i = j + 1; while (i < nums.length) { if (nums[i] !== 0) { const temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; break; } i++; } } } return nums; };
|
依次定点法
有没有办法可以更快,步骤更少呢。上面我们还要向后遍历来找非0值,能不能去掉这一步。其实是可以的,甚至交换那一步也可以简化,我们用一个指针来分割,该指针的左边一定是非0值,然后依次从左到右交换过去,并更新指针位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var moveZeroes2 = function (nums) { if (nums.length === 0 || nums.length === 1) { return nums; } let i = 0; for (let j = 0; j < nums.length; j++) { const temp = nums[j]; nums[j] = 0; if(temp !== 0){ nums[i] = temp; i++; } } return nums; };
|
还能有变体,也可以先交换,在看分割指针和当前循环指针是否指向同一处,如果不在同一处,说明必定存在0,那我们把0赋值给当前位置完成交换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var moveZeroes3 = function (nums) { if (nums.length === 0 || nums.length === 1) { return nums; } let i = 0; for (let j = 0; j < nums.length; j++) { if (nums[j] !== 0) { nums[i] = nums[j]; if (j !== i) { nums[j] = 0; } i++; } } return nums; };
|
最终代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var moveZeroes = function (nums) { if (nums.length === 0 || nums.length === 1) { return nums; } let i = 0; for (let j = 0; j < nums.length; j++) { const temp = nums[j]; nums[j] = 0; if(temp !== 0){ nums[i] = temp; i++; } } return nums; };
|
参考链接