[LeetCode移动零] | 刷题打卡

189 阅读2分钟

[LeetCode移动零] | 刷题打卡

第12题了,本想发个大招,但时间有限,题库里没刷过特别难的双指针问题,来一道移动0的问题放松下!

一直有刷题习惯,最近才看到掘金举办了刷题活动,特来参加!此题为第12题。不得不说掘金的主题就是漂亮呀!赞。

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述:

移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

例1:

输入: nums = [0, 1, 0, 3, 12],
输出: [1, 3, 12, 0, 0].

例2:

输入: nums = [0, 0, 0, 3, 1],
输出: [3, 1, 0, 0, 0].

例3:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

说明:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。

二、思路分析:

方法
描述
时间复杂度
空间复杂度
双指针同向双指针,两种做法O(n)O(n)(1)(1)
第一步left记录新数组,right记录旧数组,O(n)O(n)(1)(1)
第二步遍历旧数组,移动right指针,旧数组不为0leftright同时移动O(n)O(n)(1)(1)
第三步旧数组为0,仅right移动,left记录为0的位置O(n)O(n)(1)(1)
第四步旧数组不为0时,有两种做法:
方法1:将rightleft的值互换,leftright同时移动
O(n)O(n)(1)(1)
第五步方法2:将right的值赋值给left位置,在遍历结束之后,将[0,1,2...left,..right]left->right之间非0的值重写为0O(n)O(n)(1)(1)

三、AC 代码:

两种思路 way1在注释中 way2已经打开

// @lc code=start
class Solution {
    public void moveZeroes(int[] nums) {
        int left = 0;
        int right = 0;
        // ways 1:
        // while (right < nums.length) {
        // if (nums[right] != 0) {
        // int temp = nums[left];
        // nums[left] = nums[right];
        // nums[right] = temp;
        // left++;
        // }
        // right ++;
        // }
        // way 2
        while (right < nums.length) {
            if (nums[right] != 0) {
                if (left != right) {
                    nums[left] = nums[right];
                }
                left++;
            }
            right++;
        }
        while (left < nums.length) {
            if (nums[left] != 0) {
                nums[left] = 0;
            }
            left++;
        }
    }
}
// @lc code=end

四、总结:

此次双指针,leftright指向了两个数组,不同之处是:

  • 思路1是创建了临时数组,for循环一次
  • 思路2是在原数组上抽象了一个不存在的数组,需要while循环两次,第一次left记录了不为0的个数,第二次从nums[left]开始,将非0元素全部置为0