【Moving Zero】

moving zero

Given an array nums, write a function to 0move to the end of the array while maintaining the relative order of the nonzero elements.

Note that arrays must be manipulated in-place without copying them.

Example 1:

Input: nums = [0,1,0,3,12]
Output: [1,3,12,0,0]

Example 2:

Input: nums = [0]
Output: [0]

hint:

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

Advanced: Can you minimize the number of operations completed?

Author: LeetCode
Link: https://leetcode.cn/leetbook/read/all-about-array/x9rh8e/
Source: LeetCode

class Solution {
    
    
public:
    void moveZeroes(vector<int>& nums) {
    
    
        int i = 0, j = 0;
        // 遍历整个数组,将所有非零元素都移动到数组的前面
        while (j < nums.size()) {
    
    
            if (nums[j] != 0) {
    
    
                nums[i] = nums[j];
                i++;
            }
            j++;
        }
        // 将剩余的位置都填充为 0
        while (i < nums.size()) {
    
    
            nums[i] = 0;
            i++;
        }
    }
};

Specifically, we define two pointers iand jand initialize them both to 0. Then, we use jto iterate over the entire array, and for each element, if it is not 0, copy it to nums[i]the position of and increment the value iof . In this way, iit points to the position of the next non-zero element to be filled. When the traversal is complete, all non-zero elements have been filled to the front of the array in the original order.

Next, we use another while loop to fill the remaining positions with zeros. Specifically, we start from the position iof and assign 0 to the elements in the array continuously until the end of the array.

It should be noted that the time complexity of this algorithm is O(n), where n represents the length of the array. Since only a constant number of extra variables need to be used, the space complexity is O(1).

Description: Enter [0,1,0,3,12]

1. 初始化两个指针 `i` 和 `j`,它们都从 0 开始。
2. 使用一个 while 循环遍历整个数组,当 `j` 指针小于数组长度时,进入循环。
3. 如果 `nums[j]` 不等于 0,将 `nums[j]` 的值赋给 `nums[i]`,然后将指针 `i` 向前移动一位。
4. 不论 `nums[j]` 是否等于 0,指针 `j` 都会向前移动一位。

下面是对这段代码在给定数组 `[0, 1, 0, 3, 12]` 上的执行过程的详细说明:

1. 初始化:`i = 0`, `j = 0`, `nums = [0, 1, 0, 3, 12]`
2. `j = 0`,`nums[j] = 0`,跳过。`i = 0`, `j = 1`
3. `j = 1`,`nums[j] = 1`,`nums[i] = nums[j]`。`nums = [1, 1, 0, 3, 12]`。`i = 1`, `j = 2`
4. `j = 2`,`nums[j] = 0`,跳过。`i = 1`, `j = 3`
5. `j = 3`,`nums[j] = 3`,`nums[i] = nums[j]`。`nums = [1, 3, 0, 3, 12]`。`i = 2`, `j = 4`
6. `j = 4`,`nums[j] = 12`,`nums[i] = nums[j]`。`nums = [1, 3, 12, 3, 12]`。`i = 3`, `j = 5`
7. `j >= nums.size()`,循环结束。

此时,非零元素已经按照相对顺序移动到数组的前面。

Advanced: Can you minimize the number of operations completed?

In order to reduce the number of times the operation is done, we can slightly modify the above double pointer arithmetic. Here, we will directly exchange with the element pointed to iby , instead of simply assigning the non-zero element to nums[i]. In this way, when the pointer jhas traversed the entire array, we have completed the entire process, and there is no need to traverse the array again to fill with 0.

Here is the modified code:

void moveZeroes(std::vector<int>& nums) {
    
    
    int i = 0;

    for (int j = 0; j < nums.size(); ++j) {
    
    
        if (nums[j] != 0) {
    
    
            // 当 i != j 时,交换元素;当 i == j 时,不进行操作
            if (i != j) {
    
    
                std::swap(nums[i], nums[j]);
            }
            i++;
        }
    }
}

This method completes the operation in one traversal, reducing the number of operations. In the best case, i.e. no zeros in the array, this algorithm will take half as many operations. In the worst case, that is, the array is full of 0s, the number of operations of this algorithm will be the same as before.

Guess you like

Origin blog.csdn.net/u013454780/article/details/130544497