第80期-基础技巧:双指针 删除有序数组中的重复项

1 问题描述

给你一个有序数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

示例 1:

输入: nums = [1,1,2]
输出: 2, nums = [1,2]
解释: 函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 2:

输入: nums = [0,0,1,1,1,2,2,3,3,4]
输出: 5, nums = [0,1,2,3,4]
解释: 函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

初始代码

from typing import List
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        #在此之间填写代码

print(Solution().removeDuplicates([1,1,2]))
print(Solution().removeDuplicates([0,0,1,1,1,2,2,3,3,4]))
View Code

2 解题思路

  • 标签:双指针
  • 这道题目的要求是:对给定的有序数组 nums 删除重复元素,在删除重复元素之后,每个元素只出现一次,并返回新的长度,上述操作必须通过原地修改数组的方法,使用 O(1) 的空间复杂度完成。
  • 由于给定的数组nums是有序的,因此对于任意 i<j,如果 nums[i]=nums[j],则对任意i≤k≤j,必有nums[i]=nums[k]=nums[j],即相等的元素在数组中的下标一定是连续的。利用数组有序的特点,可以通过双指针的方法删除重复元素。

#3 解题方法

from typing import List
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        i,j=1,1
        n=len(nums)
        while i<n:
            if nums[i]!=nums[i-1]:
                nums[j]=nums[i]
                j+=1
            i+=1
        print(nums[:j])
        return j

print(Solution().removeDuplicates([1,1,2]))
print(Solution().removeDuplicates([0,0,1,1,1,2,2,3,3,4]))
View Code

第1-3,14-15行: 题目中已经给出的信息,运行代码时要根据这些代码进行编辑
第4行: 定义变量i,j分别赋值1,1,用于表示快慢指针
第5行: 定义变量n并赋值nums列表的长度
第6行: 当快指针i小于n时,执行循环
第7行: 判断快指针对应的元素是否与其前一个元素相等
第8-9行: 若不相等,则令慢指针对应的元素等于快指针对应的元素
第10行: 慢指针进一
第11行: 不管是否相等,快指针都进一
第12行: 输出列表慢指针改变过的那一段列表
第13行: 输出改变过的列表长度

代码运行结果为:
image.jpg

#算法讲解

这里用到了基础技巧:双指针,简单讲解下这个技巧:
什么是双指针(对撞指针、快慢指针)
双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。


用法
对撞指针
对撞指针是指在有序数组中,将指向最左侧的索引定义为左指针(left),最右侧的定义为右指针(right),然后从两头向中间进行数组遍历。

对撞数组适用于有序数组,也就是说当你遇到题目给定有序数组时,应该第一时间想到用对撞指针解题。

快慢指针
快慢指针也是双指针,但是两个指针从同一侧开始遍历数组,将这两个指针分别定义为快指针(fast)和慢指针(slow),两个指针以不同的策略移动,直到两个指针的值相等(或其他特殊条件)为止,如fast每次增长两个,slow每次增长一个。

 

posted @ 2022-01-06 20:18  LG03  阅读(75)  评论(0编辑  收藏  举报