问题描述:
一、常规解法
(1) 基本实现思路
先将数组中非零的元素取出来:
然后将非零元素放回到数组中:
最后将剩余的元素赋予0:
(2)代码实现
// 时间复杂度: O(n)
// 空间复杂度: O(n)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
vector<int> nonZeroElements;
// 将vec中所有非0元素放入nonZeroElements中
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i])
nonZeroElements.push_back(nums[i]);
// 将nonZeroElements中的所有元素依次放入到nums开始的位置
for(int i = 0 ; i < nonZeroElements.size() ; i ++)
nums[i] = nonZeroElements[i];
// 将nums剩余的位置放置为0
for(int i = nonZeroElements.size() ; i < nums.size() ; i ++)
nums[i] = 0;
}
};
int main() {
int arr[] = {0, 1, 0, 3, 12};
vector<int> vec(arr, arr + sizeof(arr)/sizeof(int));
Solution().moveZeroes(vec);
for(int i = 0 ; i < vec.size() ; i ++)
cout << vec[i] << " ";
cout << endl;
return 0;
}
二、第一种优化方法
(1)基本思路
1.将蓝色箭头设为k,红色箭头设为i:
2.k=0,遍历i,如果num[i]>0,nums[k] = nums[i];
然后k++,i++
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i])
nums[k++] = nums[i];
-----------------------------------------------------------
--------------------------------
------------------------------------------------
(2)当i = nums.size(),将nums剩余的位置放置为0
-----------------------------------------------------
这一部分代码:
// 将nums剩余的位置放置为0
for(int i = k ; i < nums.size() ; i ++)
nums[i] = 0;
(3)第一种优化方法的完整代码实现
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0; // nums中, [0...k)的元素均为非0元素
// 遍历到第i个元素后,保证[0...i]中所有非0元素
// 都按照顺序排列在[0...k)中
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i])
nums[k++] = nums[i];
// 将nums剩余的位置放置为0
for(int i = k ; i < nums.size() ; i ++)
nums[i] = 0;
}
};
三、第二种优化方法
第一种优化的方法需要我们去补充最后的两个0,那么我们能不能当遍历完成,0自动在数组的后面?
(1)
当k=0,i=1时,num[1] = 1,非0,此时我们swap(nums[k] , nums[i]);
然后k++:
------------------------------------
-------------------------------
--------------------------
(2)当i = 3,k = 2时,我们swap(nums[k] , nums[i]);
--------------------------------------
---------------------
(3)第二种优化方法完整代码实现:
// 原地(in place)解决该问题
// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0; // nums中, [0...k)的元素均为非0元素
// 遍历到第i个元素后,保证[0...i]中所有非0元素
// 都按照顺序排列在[0...k)中
// 同时, [k...i] 为 0
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i])
swap(nums[k++] , nums[i]);
}
};
四、第三种优化方法
(1)在第二种方法中,当数组中所有元素都非0时,每一次循环都会自己和自己交换,
所以,如果i = k时,我们直接k++即可;
当i!= k时,我们在调用swap(nums[k++] , nums[i])
(2)第三种优化方法代码完整实现:
// 原地(in place)解决该问题
// 时间复杂度: O(n)
// 空间复杂度: O(1)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int k = 0; // nums中, [0...k)的元素均为非0元素
// 遍历到第i个元素后,保证[0...i]中所有非0元素
// 都按照顺序排列在[0...k)中
// 同时, [k...i] 为 0
for(int i = 0 ; i < nums.size() ; i ++)
if(nums[i])
if(k != i)
swap(nums[k++] , nums[i]);
else
k ++;
}
};
参考资料:
https://coding.imooc.com/class/chapter/82.html#Anchor