「LeetCode」283.移动零

156 阅读1分钟

「这是我参与2022首次更文挑战的第21天,活动详情查看:2022首次更文挑战」。

题目描述🌍

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

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1

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

示例 2

输入: nums = [0]
输出: [0]

提示

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

双指针法🔍

解题思路

这道题的解题思路和之前做过的 2 题很像:

所谓的双指针:通常是慢指针指向有效数组末尾,快指针用于遍历数组(以上提及的两题和该题都是如此)

思路:指针 j 顺序遍历数组,一旦遇到 非0 元素,将其覆盖到指针 i 指向的有效数组末尾。此时可以进行两种"移动零"的操作(以下代码演示第二种):

  1. 再遍历一次数组,将 j 指针后边的元素全部赋值为 0.
  2. 首次遍历数组且赋值 nums[i] = nums[j] 后,判断 ij 指针是否指向同一个元素,若不同,则将 j 指针指向的位置赋值为 0.

代码

Java

class Solution {
    public void moveZeroes(int[] nums) {
        // 指针 i 指向有效数组的末位
        // 指针 j 用于遍历数组
        int i = 0;
        for (int j = 0; j < nums.length; j++) {
            if (nums[j] != 0) {
                nums[i] = nums[j];
                if (i != j)
                    nums[j] = 0;
                i++;
                // 以上四行代码也可简写为如下代码
//                nums[i++] = nums[j];
//                nums[j] = ((i - 1) == j ? nums[j] : 0);
            }
        }
    }
}

C++

class Solution {
public:
    void moveZeroes(vector<int> &nums) {
        int left = 0;
        int n = nums.size();
        for (int right = 0; right < n; ++right) {
            if (nums[right] != 0) {
                nums[left] = nums[right];
                if (left != right)
                    nums[right] = 0;
                left++;
            }
        }
    }
};

时间复杂度:O(n)O(n)

空间复杂度:O(1)O(1)

最后🌅

该篇文章为 「LeetCode」 系列的 No.19 篇,在这个系列文章中:

  • 尽量给出多种解题思路
  • 提供题解的多语言代码实现
  • 记录该题涉及的知识点

👨‍💻争取做到 LeetCode 每日 1 题,所有的题解/代码均收录于 「LeetCode」 仓库,欢迎随时加入我们的刷题小分队!