題目
自己寫透過的:
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] == 0
和 nums[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的元素來進行交換。
再附上分析的兩張圖:
第二張圖其實就是我踩的第二個坑的第一個不透過的案例
最後看了下官方題解,也有些收穫
官方程式碼:
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 ++
,來滿足左指標左邊均為非零數,同時為下個可能要更換的數做準備;