4.19——数组双指针——26. 删除有序数组中的重复项 & 27. 删除有序数组中的重复项II & 80. 删除有序数组中的重复项 II

2023-06-09,,

第一次做到数组双指针的题目是80:

因为python的List是可以用以下代码来删除元素的:

del List[index]

所以当时的我直接用了暴力删除第三个重复元素的做法,大概代码如下:

n = len(nums)
for i in range(n):
if 重复了第i个:
del nums[i]
i -= 1

在出来7%+5%的提交成功以后,我去看了题解,才发现了可以用双指针做...

在宫水三叶姐的题解中,能使用双指针的本质是利用了「数组有序 & 保留逻辑」两大主要性质。最早接触双指针,还是在取单链表中间节点时,使用快慢指针来对链表进行遍历。看了leetcode的标签,双指针有很多应用,尤其实在数组和字符串(类似于字符数组)的处理中,以后有遇到双指针处理数组的类似题目会添加在这篇随笔中。

-------------------------------------------------------------------------------------

part1.数据有序,相同元素保留 k 位

在这种题目中,核心要求是:不要使用额外的数组空间,你必须在 原地修改输入数组 并在使用 O(1) 额外空间的条件下完成。

核心思想:使用快慢指针遍历数组,快指针遍历数组中的所有元素,慢指针指向最后一个“合法”的数据,这些数据构成最后的合法数组。

在慢指针“指向”的nums[:slow]的合法数组满足以下条件:

    nums[:slow](后续称为slow数组)保持非降序
    nums[:slow](所有元素) <= nums[fast]
    nums[:slow]中的每个元素最多只重复k次

由1+2,判断当前遍历到的元素nums[fast]是否已经重复了k次,就可以用以下代码来判断:

if nums[fast] != nums[slow - k]:
# 处理 by Python

这行核心代码的判断逻辑如下:

根据2,当前遍历到的元素nums[fast]不小于slow数组的所有数;

根据1,nums[:slow]中的元素是非降序的;

那么当前遍历到的元素nums[fast]只会跟slow数组中最大的数字,也就是最后的数字nums[:slow]相比。同时因为1,保证了这个数字只可能在数组的末尾重复若干次。

这样,只要将nums[fast]跟slow数组的倒数第k个数nums[slow - k]相比:

  如果相同,说明nums[fast]已经重复了k次,nums[fast]不需要存储到slow数组中,继续向下遍历:

fast += 1

  如果不同,说明nums[fast]还未重复了k次,nums[fast]仍需要存储到slow数组中,将nums[fast]复制到slow数组中,数组边界+1,继续向下遍历:

nums[slow] = nums[fast]
slow += 1
fast += 1

在构成的if语句中有nums[slow - k],需要保证数组不越界,所以最后的算法框架如下:

def removeDuplicates(self, nums):
slow = 0
for fast in range(len(nums)):
if slow < k or nums[fast] != nums[slow - k]:
nums[slow] = nums[fast]
slow += 1
return slow

end

----------------------------------------------------------------------------------------------

4.19——数组双指针——26. 删除有序数组中的重复项 & 27. 删除有序数组中的重复项II & 80. 删除有序数组中的重复项 II的相关教程结束。

《4.19——数组双指针——26. 删除有序数组中的重复项 & 27. 删除有序数组中的重复项II & 80. 删除有序数组中的重复项 II.doc》

下载本文的Word格式文档,以方便收藏与打印。