问题描述
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例
分析
解法一:
遍历数组直接将非零元素全部移动到前面来,然后将数组后面补上零
解法二:
使用快慢指针,慢指针指向已经处理好的非零元素的尾部,快指针指向未处理好的元素的头部。
当快指针不断前移并且指向的元素不为0时,将其与慢指针指向的元素交换。
然后慢指针前移一位。
注意到以下性质:
- 慢指针左边均为非零数
- 快指针左边直到左指针处均为零
因此每次交换,都是将左指针的零与右指针的非零数交换,且非零数的相对顺序并未改变。
代码实现
解法一:
public void moveZeroes1(int[] nums) {
int index = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
nums[index++] = nums[i];
}
}
for (int i = index; i < nums.length; i++) {
nums[i] = 0;
}
}
//在上面解法的基础上直接将nums[index] 与 nums[i]交换,这样第二个循环就不用写了
public void moveZeroes2(int[] nums) {
int index = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
int temp = nums[index];
nums[index] = nums[i];
nums[i] = temp;
index++;
}
}
}
解法二:
public void moveZeroes3(int[] nums) {
int slow = 0, fast = 0;
while (fast < nums.length) {
if (nums[fast] != 0) {
int temp = nums[slow];
nums[slow] = nums[fast];
nums[fast] = temp;
slow++;
}
fast++;
}
}