题目(这题是做过的,所以只考虑优化)
给定一个数组 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
进阶:你能尽量减少完成的操作次数吗?
代码实现
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int zero_ptr = 0, nonzero_ptr = 0, n = nums.size();
while(zero_ptr < n && nonzero_ptr < n) {
if(nums[zero_ptr] != 0) ++zero_ptr;
if(nums[nonzero_ptr]==0 || nonzero_ptr<zero_ptr) ++nonzero_ptr;
if(zero_ptr<n && nonzero_ptr<n) {
if(nums[zero_ptr]==0 && nums[nonzero_ptr]!=0) {
swap(nums[zero_ptr++], nums[nonzero_ptr++]);
}
}
}
}
};
优化
- 时间复杂度其实已经基本是最好了,但是空间复杂度仍有优化的空间。
- 总体的逻辑还是遍历整个数组,然后控制zero_ptr,如果发现非0数就交换位置,如果指向的是两个非0数,那么他们会发生两次swap(分别指到数a和数b时),所以非0元素是保序的。
- 而因为在0元素时不发生交换left_zero不增加,所以就会控制0元素一直在往后滚动。
- 复现:
-
class Solution { public: void moveZeroes(vector<int>& nums) { int left_zero = 0; for(int i = 0; i < nums.size(); i++) { if(nums[i] != 0) { swap(nums[i], nums[left_zero]); left_zero++; } } } };