《算法通关村——双指针的妙用》

文章介绍了在数组中删除特定值和去除有序数组重复项的三种指针技巧,包括原地移除、快慢双指针和对撞双指针的扩展版本。

目录

删除元素专题

1.原地移除所有数值等于val的元素

1)快慢双指针

2)对撞双指针

3)拓展:"对撞双指针+覆盖"法

2.删除有序数组的重复项


删除元素专题

1.原地移除所有数值等于val的元素

1)快慢双指针
public static int removeElement(int[] nums, int val) {
    int slow = 0;
    //fast充当了快指针的角色
    for (int fast = 0; fast < nums.length; fast++) {
        if (nums[fast] != val) {
            nums[slow] = nums[fast];
            slow++;
        }
    }
    //最后剩余元素的数量
    return slow;
}

快慢指针相当于定义了两个变量,fast走得快,遍历数组nums,找到nums中等于val的元素拷贝到slow走过的轨迹中。

2)对撞双指针
 public int removeElement(int[] nums, int val) {
        int left=0;
        int right=nums.length-1;
        for(left=0;left<=right; ){
            if(nums[left]==val&&nums[right]!=val){
                int temp=nums[left];
                nums[left]=nums[right];
                nums[right]=temp;
            }
            if(nums[left]!=val) left++;
            if(nums[right]==val) right--;
        }
        return left;
    }

left,right两个从数组头和尾分别开始走,当nums[left]等于val并且nums[right]不等于right的时候交换数组中两个位置的元素,否则都相向遍历,直到left==right,遍历完成,最后返回的left就是删除val元素后nums数组剩余元素的个数。

3)拓展:"对撞双指针+覆盖"法
public int removeElement(int[] nums, int val) {
        int right=nums.length-1;
        for(int left=0;left<=right; ){
            if(nums[left]==val){
                nums[left]=nums[right];
                right--;
            }else{
                left++;
            }
        }
        return right+1;
    }

对方法2的拓展,把交换改为覆盖,我们的目的是删除val元素,所以并不关心val元素到哪里,因此覆盖一定程度上可以减少代码量,最后返回right+1。

为什么right要加一?        当nums[left]==val时,我们用nums[right]覆盖nums[left],并使right往前移一位, 因为开始right是作为索引存在,最后要返回的是剩余元素的个数。

补充一下:方法二中为什么返回left,开始时设置left=0,而后只要nums[left]!=val就使left++,交换后还会判断一下使left++,自然返回的就是删除val元素后nums数组剩余元素的个数了。

2.删除有序数组的重复项

public int removeDuplicates(int[] nums) {
        int slow=1;
        for(int fast=0;fast<nums.length;fast++){
            if(nums[fast]!=nums[slow-1]){
                nums[slow]=nums[fast];
                slow++;
            }
        }
        return slow;
    }

先使slow=1,第一个元素算一个,进入for循环fast遍历数组,遇到新元素添加到slow走过的轨迹,slow++,最后返回slow,数组剩余元素的个数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值