双指针算法介绍
双指针算法一般分为左右指针和同向指针。
左右指针就是一个指针从数组的最左端出发,另一个指针从数组的最右端出发,直到两个指针相遇或是错开时结束移动或是跳出循环。基于这个操作我们可以解决许多看似困难实则简单的题目,如将数组内容分成左右两个部分
同向指针为两个指针朝同一个方向进行移动,两个指针或是移动速度不一致,或是起点不一致,在数组上或是链表上移动, 此方法对于解决环形链表或是数组有很大帮助。
283. 移动零 - 力扣(LeetCode)
点击题目可跳转到力扣页面

题目分析
题目要求我们把数组中所有的零移动到数组的末尾,同时保持其他元素的相对位置不发生变化,同时要在不复制数组的情况下完成。
我们可以理解为,题目要我们把数组中,零的部分放在右边,非零部分在保存相对顺序的情况下放在数组的左端,这样数组就分成了两个部分:!0|0,这是一个双指针算法典型的用法。
题目解答
定义两个指针:left=0,right=0;(假设数组为num)
若num.lengrh==1,直接返回num;
若num.lengrh()!=1:
循环left指针移动;
若numleft==0,不操作,left++;
若numleft!=0,交换数组元素numright和numleft,left++,right++;
注:这样right和left相当于一条分界线,!0|right|0|left|未处理数
若left>num.len,退出循环
此时,数组的左端均为非零数,右端均为零,同时也可以保持非零数直接的顺序没有发生改变
代码实现(Java)
class Solution {
public void moveZeroes(int[] nums) {
if(nums==null){
return;
}
int cur=0;
int dest=0;
while (cur<nums.length){
if(nums[cur]==0){
cur++;
}else {
//交换
int tmp=nums[cur];
nums[cur]=nums[dest];
nums[dest]=tmp;
dest++;
cur++;
}
}
}
}
提交代码

1089. 复写零 - 力扣(LeetCode)
题目分析

题目分析
题目要求我们将数组上原有的零复写一遍,将其余元素往右移动,并且不要超过原数组长度,若我们按正常顺序从前往后,遇到零就将下一个元素改为零的话,后面的元素就会被零覆盖,无法进行下去,不妨我们换个思路,从后往前开始复写,这样前一个元素就不会因为被赋值为零而丢失。因此我们需要先找到最后一个需要复写的位置。
题目解答
- 定义两个指针:dest=0,cur=0;
- 循环cur,退出循环:(cur < n)
- 若cur=0,dest向前走两步,cur向前走一步
- 若cur!=0,dest向前走一步,cur向前走一步
- 若是dest>=arr.length-1,break;
- 出循环,处理边界:若dest>arr.length-1,arr.length-1赋值为0,dest赋值为arr.length-2,cur赋值为cur-1;若dest=arr.length-1,dest赋值为零,cur--;dest--;
- 循环
- 若cur==0,arr.dest--=0;arr.dest--=0;cur--;
- 若cur!=0,arr.dest--=arrcur--;
- 当cur<0时,退出循环
代码实现(Java)
class Solution {
public void duplicateZeros(int[] arr) {
//找到最后一个复写的数字
int cur=-1;
int dest=-1;
while (dest<arr.length-1){
//要先判断dest是否越界,才能cur++
cur++;
if(arr[cur]==0){
dest+=2;
}else {
dest++;
}
}
//开始复写
//处理dest越界情况
if (dest>arr.length-1){
dest=arr.length-1;
arr[dest--]=0;
cur--;
}
while (cur>=0){
if(arr[cur]==0){
arr[dest]=0;
dest--;
arr[dest]=0;
dest--;
}else {
arr[dest]=arr[cur];
dest--;
}
cur--;
}
}
}
提交代码
