使用方法有双指针(覆盖+填充)法和双指针(交换)法,关键点在于快慢指针遍历时选择哪种方法更简便。
双指针(覆盖+填充):时间复杂度:O(log n^2),空间复杂度:O(1)
双指针(覆盖+填充)思路:
- 利用双指针遍历两次数组
- 第一遍双指针遍历将数组中的非零数向前移动,即fast指针在遍历中指向的值为非零值就赋给slow指针指向的位置
- 第二遍补齐slow指针后面即新非零数组后面的零
双指针(覆盖+填充)代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slow = 0;
for (int fast = 0; fast < nums.size(); fast++) {
if (nums[fast] != 0) {
nums[slow] = nums[fast];
slow++;
}
}
while (slow != nums.size()) {
nums[slow] = 0;
slow++;
}
}
};
双指针(交换):时间复杂度:O(log n),空间复杂度:O(1)
双指针(交换)思路:
- 利用双指针遍历一次数组
- fast指针在遍历中指向的值为非零值时,就与slow指针指向的位置交换,这样将非零值的位置向前移动,同时还将零向后移动了。
双指针(交换)代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slow = 0;
for (int fast = 0; fast < nums.size(); fast++) {
if (nums[fast] != 0) {
swap(nums[slow], nums[fast]);
slow++;
}
}
}
};
双指针(覆盖+填充)法的优点在于它要对每个元素进行一次赋值操作,但是对于原始结果为0的位置,也需要进行一次赋值操作。与此不同的是,双指针(交换)法每次需要进行两次赋值操作(a=b; b=0;),但是对于后续原始结果为0的位置,可以不再进行任何操作。