一、题目要求
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
二、初步解法
2.1 初步思想
使用快慢指针,最开始都指向数组头,使用一个变量在遍历的时候记录0的数量为temp。 若快指针指向0元素则临时变量+1,快指针前移。 若快指针指向非零元素则与慢指针指向位置互换元素,随后两个指针一起后移。 当快指针遍历到数组末尾的时候跳出循环,之后将数组后temp个元素替换为0。
2.2 代码实现
class Solution {
public void moveZeroes(int[] nums) {
int fastPtr = 0,slowPtr = 0,temp = 0;
while (fastPtr < nums.length) {
//若指向0元素,仅快指针后移,零记录+1
if (nums[fastPtr] == 0) {
fastPtr++;
temp++;
}
//否则快慢指针一起后移
else {
swap(nums,fastPtr,slowPtr);
fastPtr++;
slowPtr++;
}
}
for (int i = nums.length-temp; i < nums.length; i++) {
nums[i] = 0;
}
}
public void swap(int[] nums,int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
2.3 运行结果
时间复杂度O(N),空间复杂度O(1),但进行了两轮遍历,执行用时不理想。
三、优化解法
3.1优化思想
何必交换呢?既然后面的数最终都会被0覆盖,且指针不回头,直接用快指针指向元素覆盖慢指针指向的元素就可以了。
3.2 代码实现
class Solution {
public void moveZeroes(int[] nums) {
int fastPtr = 0,slowPtr = 0,temp = 0;
while (fastPtr < nums.length) {
if (nums[fastPtr] == 0) {
fastPtr++;
temp++;
}
else {
nums[slowPtr] = nums[fastPtr];
fastPtr++;
slowPtr++;
}
}
for (int i = nums.length-temp; i < nums.length; i++) {
nums[i] = 0;
}
}
}