算法通关村——双指针的妙用(删除元素专题)

1. 双指针专题

快慢指针
对撞型指针

1. 移除元素

移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

1.2 分析

1.2.1 双指针法

设置slow,fast指针,使得指针slow之前的数据都是不包含val的,fast一直向后走,如果不是val,slow位置写入fast的值。前半部分有效,后半部分无效

 public int removeElement(int[] nums, int val) {
    
    
        int slow =0;
        for(int fast =0; fast<nums.length; fast++){
    
    
            if(nums[fast]!=val){
    
    
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }

在这里插入图片描述
时间复杂度:O(n) 遍历了一个数组的长度
空间复杂度:O(1)就使用了slow记录数组长度

1.2.2 对撞双指针

设置左右两个指针,找到右边不是val的值来替代左边是val的情况,也是左边的元素都是有效的。

    public int removeElement(int[] nums, int val) {
    
    
        int left =0;
        int right = nums.length -1;
        for(left =0;left<=right;){
    
    
            if(nums[right]!=val && nums[left] == val){
    
    
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right]=temp;
            }

            if(nums[left]!=val) left++;
            if(nums[right]==val) right--;
        }
        return left;
    }

在这里插入图片描述
时间复杂度:O(n)遍历了数组的长度
空间复杂度:O(1)

1.2.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. 删除有序数组中的重复项

删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。

扫描二维码关注公众号,回复: 16249542 查看本文章

2.1 分析

2.1.1 使用快慢双指针

依然设置快慢指针,只有快指针和慢指针不相同的时候才能将慢指针进行替换,然后慢指针再次自增。有个小的优化点就是一开始的slow=0不需要处理,因为如果后面有元素和0索引一样,只需要换掉后面的元素就可以了。

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;
    }

在这里插入图片描述
时间复杂度:O(n)
空间复杂度:O(1)

总结

对于这一题删除指定元素,使用快慢指针的效率还是很高的,通过这个专题了解到了一些常用双指针的使用方式

猜你喜欢

转载自blog.csdn.net/qq_52843958/article/details/131921034
今日推荐