原题:
给定一个数组 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
分析:
双指针算法的过程,举个简单的例子
指针位置 | a指针 | ||||
数组 | 0 | 1 | 0 | 3 | 12 |
数组下标 | 0 | 1 | 2 | 3 | 4 |
指针位置 | b指针 |
如上表,在遍历数组的时候我们设置两个指针a和b,起始两个指针都在数组下标为0的位置,移动和交换逻辑是,a指针每次移动一个位置,如果移动后的位置是0,则继续移动,同时b指针不动;如果移动后的位置是非0,此时a与b下标对应的元素交换位置。
接下来我们进行第一次移动。a指针后移一位,元素此时非0,按照规则,b指针对应的元素跟a指针元素进行交换,同时b指针后移1位。
指针位置 | a指针 | ||||
数组 | 1 | 0 | 0 | 3 | 12 |
数组下标 | 0 | 1 | 2 | 3 | 4 |
指针位置 | b指针 |
继续第二次移动,a指针继续后移,到达数组下标2的位置,此时元素等于0,不做操作。
指针位置 | a指针 | ||||
数组 | 1 | 0 | 0 | 3 | 12 |
数组下标 | 0 | 1 | 2 | 3 | 4 |
指针位置 | b指针 |
继续第三次移动,a指针继续后移,到达数组下标3的位置,此时元素非0,则需要交换a、b指针对应元素的位置,同时b指针后移1位。
指针位置 | a指针 | ||||
数组 | 1 | 3 | 0 | 0 | 12 |
数组下标 | 0 | 1 | 2 | 3 | 4 |
指针位置 | b指针 |
继续第四次移动,a指针后移一位,到达数组下标4的位置,此时元素非0,需交换a和b下标对应的数据,同时b指针后移一位。此时遍历已经结束,数组中的0已经全部移动到数组末位。这就是移动零的一种双指针解法。
指针位置 | a指针 | ||||
数组 | 1 | 3 | 12 | 0 | 0 |
数组下标 | 0 | 1 | 2 | 3 | 4 |
指针位置 | b指针 |
下面开始写代码,老样子,先新建个类,同时写一个方法,入参就是数组。
public class SolutionMoveZeroes {
public void moveZeroes(int[] nums){
//声明指针,起始位置是0
int b = 0;
for(int a = 0; a < nums.length; a++){
}
}
}
for循环内部开始判断,a坐标的元素非0时,交换a、b下标对应的位置,同时b下标右移一位。
public class SolutionMoveZeroes {
public void moveZeroes(int[] nums){
//声明指针,起始位置是0
int b = 0;
for(int a = 0; a < nums.length; a++){
//声明一个临时整数用来交换数据
int temp = 0;
//a指针位置非0,交换a b元素
if (nums[a] != 0) {
temp = nums[b];
nums[b] = nums[a];
nums[a] = temp;
b++;
}
}
}
}
以上就是移动0的一种双指针解法,难点在于双指针的过程一般可能想不到。