今天是小呆刷题的第4天,今天的题目是:力扣(LeetCode)的第283题,移动零
题目要求
给定一个数组nums
,编写一个函数将所有0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意,必须在不复制数组的情况下原地对数组进行操作。
示例:
1 2
| 输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0]
|
提示:
1 <= nums.length <= 10^4
-2^31 <= nums[i] <= 2^31 - 1
解题思路
刷题的第4天,遇到这种原地操作数组的题,看起来要求跟第27题移除元素很相似,唯一的区别是把数组里所有的0
移到末尾。小呆首先的思路是考虑用双指针算法,所以第一步是先将非0
的元素移到前面。以示例代码为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
var moveZeroes = function(nums) { if(nums.length === 0) return let fast = 0, slow = 0 while(fast < nums.length) { if(nums[fast] !== 0) { nums[slow] = nums[fast] slow++ } fast++ } return nums } console.log(moveZeroes[0, 1, 0, 3, 12])
|
从打印结果可以看出,非0
的代码已经都移到前面了,只需要从slow
开始,到数组末尾的数字替换为0
即可,于是有了下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
var moveZeroes = function(nums) { if(nums.length === 0) return let fast = 0, slow = 0 while(fast < nums.length) { if(nums[fast] !== 0) { nums[slow] = nums[fast] slow++ } fast++ } while(slow < nums.length) { nums[slow] = 0 slow++ } return nums } console.log(moveZeroes[0, 1, 0, 3, 12])
|
老规矩,上动图帮助理解,加深记忆:
上面的代码写了2个while
循环,那能不能只写一种循环呢?我们来改动代码试试:
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) return let fast = 0, slow = 0 while(slow < nums.length) { if(fast >= nums.length) { nums[slow] = 0 slow++ } else { if(nums[fast] !== 0) { nums[slow] = nums[fast] slow++ } fast++ } } return nums } console.log(moveZeroes[0, 1, 0, 3, 12])
|
while
循环的条件从fast
变为了slow
,当fast
的位置超出数组最后一位时,说明所有非0
的元素已经都移位好了,此时只需要将剩余的元素设为0
即可。下面是两种方式LeetCode
提交代码的结果,仅供参考。
|
执行用时 |
内存消耗 |
两个循环 |
104ms |
45.1MB |
一个循环 |
84ms |
45.8MB |
小结
到目前为止已经刷题4天了,每天一道题,数量虽然不多,但是最令小呆享受的是制作动图的过程,虽然目的是为了方便看这篇文章的同学便于理解,但无形之中也是对于小呆自身的一个理解强化。如果看这篇文章的你也跟我一样算法是短板,那就跟我一起坚持下去吧,期待花开结果的那天~
引用
力扣LeetCode的第283题-移动零
双指针技巧秒杀七道数组题目——作者:labuladong