283. 移動零

hisun9發表於2024-11-07

題目

自己寫透過的:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slow = 0, fast = 0;
        while (fast < nums.size())
        {
            if (nums[slow] == 0 && nums[fast] != 0) 
            {
                nums[slow] = nums[fast];
                nums[fast] = 0;
            }
            if (nums[slow] != 0) slow ++;
            fast ++;
        }
    }
};

基本思想就是在更換時一定是要nums[slow] == 0nums[fast] != 0同時滿足,然後slow查詢值為0的位置,當找到值為0的位置時,就不動了,直到更換了兩個數,導致這個slow位置的數不為0,然後執行slow ++,至於fast則是從頭到尾遍歷整個陣列,找出值不為0的位置,然後在nums[slow] == 0 && nums[fast] != 0滿足時,更換位置,注意每次while迴圈都要執行fast ++

然後就是在做這題的時候自己也踩了些坑,感覺還是有必要寫下的:

第一個坑就是讀題目的時候有點粗心,沒看清楚全部要滿足的條件,導致第一次寫的時候寫了如下程式碼:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int left = 0, right = nums.size() - 1;
        while (left < right)
        {
            if (nums[left] == 0)
            {
                nums[left] = nums[right];
                nums[right] = 0;
                right --;
            }
            else left ++;
        }
    }
};

這段程式碼雖然也能把所有 0 移動到陣列的末尾,但是沒有保持非零元素的相對順序。

第二個坑就是有點想當然,直接把slow ++放第一個if裡面了,也就是如下程式碼:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slow = 0, fast = 0;
        while (fast < nums.size())
        {
            if (nums[slow] == 0 && nums[fast] != 0) 
            {
                nums[slow] = nums[fast];
                nums[fast] = 0;
                slow ++;
            }
            fast ++;
        }
    }
};

錯誤的原因就是認為當更換兩個位置的數時,要讓slow ++,但是沒考慮到當slow對應的元素不為0時,也要讓slow ++,因為要讓slow位置的元素為0,等待right位置的不為0的元素來進行交換。

再附上分析的兩張圖:

img

第二張圖其實就是我踩的第二個坑的第一個不透過的案例

img

最後看了下官方題解,也有些收穫

img

官方程式碼:

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

感覺官方思路是從一個更大的更宏觀的角度去考慮的,剛開始並沒有考慮left,而是從right出發,用right來遍歷整個陣列,看right位置的數值是不是不為0,如果不為0,則一定是放在前面的,也就是slow位置,然後再slow ++,來滿足左指標左邊均為非零數,同時為下個可能要更換的數做準備;

相關文章