1.題目
題目地址(283. 移動零 - 力扣(LeetCode))
https://leetcode.cn/problems/move-zeroes/
題目描述
給定一個陣列 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.題解
2.1 雙指標法
思路
1.我們有可能會想到遍歷陣列,然後遇到0,刪除該元素,記錄個數count,最後在末尾補上count個零, 但是注意erase操作是要整體移動陣列的。 遍歷O(n) * 移動陣列O(n) = O(n^2)
2.
程式碼
- 語言支援:C++
C++ Code:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = 0, j = 0;
for(; i < nums.size(); i++){
if(nums[i] != 0){
nums[j] = nums[i];
j++;
}
}
for(; j < nums.size(); j++){
nums[j] = 0;
}
}
};
複雜度分析
令 n 為陣列長度。
- 時間複雜度:\(O(n)\)
- 空間複雜度:\(O(n)\)
2.2 最佳化(快排)
思路
我們在第一個迴圈結束後,還需要再另起一個迴圈將值賦予0,能否在第一個迴圈同時完成聚集非零數和賦0的兩個操作?
在快排中,我們每次選取一箇中間值x, 將小於這個中間值x的數放到x左邊,大於這個中間值x的放在它右邊,實現的原理就是使用了雙指標
我們這裡也可以模仿一下
程式碼
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = 0, j = 0;
for(; i < nums.size(); i++){
if(nums[i] != 0){
int temp = nums[i];
nums[i] = nums[j];
nums[j++] = temp;
}
}
}
};