Hi 大家好,我是张小猪。欢迎来到『宝宝也能看懂』系列特别篇 - 30-Day LeetCoding Challenge。
这是一个 leetcode 官方的小活动。可以在官网看到,从 4 月 1 号开始,每天官方会选出一道题,在 24 小时内完成即可获得一点小奖励。虽然奖励似乎也没什么用,不过作为一个官方的打卡活动,小猪还是来打一下卡吧,正好作为每天下班回家后的娱乐。
这里是 4 月 4 号的题,也是题目列表中的第 283 题 -- 『移动零』
题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
- 必须在原数组上操作,不能拷贝额外的数组。
- 尽量减少操作次数。
官方难度
EASY
解决思路
这道题的核心要求在于需要做原地的赋值,否则我们只需要创建一个新数组,然后根据遍历的数值向里 push
即可。
为了做到原地,我们便需要知道 0 值所在的下标位置,以及要替换成什么值。基于这个思路,我们很容易想到,可以在遍历的过程中针对值是否为 0 做区分处理。
直接方案
基于上面的思路,我们可以通过两个指针来完整整个数组的遍历。其中一个指针用于单纯的作为下标递增,另外一个指针用于标识当前还未被处理的 0 值的位置。
对于其它的非 0 值而言,两个指针会同步移动。而遇到 0 的时候,用于特殊标识的指针便停下,直到遍历的指针遇到一个非 0 的值,我们将两个值的位置进行交换,这样便完成了一次 0 值向下一个非 0 值位置的移动。而我们后续需要做的只是继续重复这个过程,直到完成遍历。这样所有的 0 值就会被移动到末尾。
具体代码如下:
const moveZeroes = nums => {
for (let i = 0, zero = 0; i < nums.length; ++i) {
if (nums[zero] === 0 && nums[i] !== 0) {
nums[zero] = nums[i];
nums[i] = 0;
}
nums[zero] !== 0 && ++zero;
}
};
换个姿势
我们可以把 nums
数组想象成有两个,一个是原始数组,一个是处理之后的数组。于是我们用一个值来遍历原始数组,而用另一个值 idx
来标识数据在处理完之后的数组中的位置。
那么在遍历的过程中,如果遇到 0 值,则 idx
不进行任何修改,而遇到非 0 值,则将其赋值给 idx
的位置,并且将 idx
进行后移。这样遍历完成后,我们便处理完了所有非 0 值的正确位置。只需要再将后面的位置全部填充 0 值即可。
具体代码如下:
const moveZeroes = nums => {
let idx = 0;
for (let i = 0; i < nums.length; ++i) {
nums[i] !== 0 && (nums[idx++] = nums[i]);
}
while (idx < nums.length) nums[idx++] = 0;
};
总结
作为『30-Day LeetCoding Challenge』的第四题,仍旧没有什么太多可说的。通过两种思路来进行了分析,希望能帮到有需要的小伙伴。
如果觉得不错的话,记得『三连』哦。小猪爱你们哟~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。