力扣-283. 移动零
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的放在它右边,实现的原理就是使用了双指针
我们这里也可以模仿一下,设置中间值为0,若是大于等于0的数全部移到右边去(j负责维护大于0的数的数组下标, i负责维护所有等于0的数组坐标)
代码
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;
}
}
}
};