80. 删除排序数组中的重复项 II
题目
给定一个增序排列数组 nums ,你需要在 原地 删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度
示例:
输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。 你不需要考虑数组中超出新长度后面的元素。
最初写的思路是这样:快指针遍历寻找与慢指针指向的相同元素,当发现不同时,快指针先后移,再判断是否相同,如果还是不同,慢指针移动到快指针的前面,快指针覆盖
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
if len(nums)<0:return 0
slower,faster=0,0
while(faster<len(nums)):
if (nums[slower]!=nums[faster]):
if(faster-slower>2):
slower=faster-1
nums[slower]=nums[faster]
faster+=1
return len(nums)
但我发现跳不出循环了,分析了一下发现代码出现一些诡异,就是虽然我找不同,但如果一开始即一样,那么快慢指针就永远不会动了,所以是因为这样才导致跳不出循环。因此我把faster+=1放到if的同级下,然后发现循环通了,但是结果没有发生预想的覆盖情况,然后经过一波操作,强行通过了第一个示例的测试,但是却达不到第二个示例的测试
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
if len(nums)<0:return 0
slower,faster=0,1
while(faster<len(nums)):
if (nums[slower]!=nums[faster]):
if(faster-slower>2):
nums[slower]=nums[faster]
faster+=1
del(nums[0])
return len(nums)
最后我还是看看答案,如果快指针和慢指针指向不同,慢指针往前推进和快指针重叠,然后进行同值覆盖,也就没变化,此时借助flag标志位来标定此时还是不需覆盖的状态,因为此时相同的数字还是在两个以内,符合题目要求,否则,如果两个指针指向的元素相同,同时flag为True,说明此时是需要执行删除覆盖,那么进行覆盖,并把flag转为false
class Solution:
def removeDuplicates(self,nums:List[int])->int:
if not nums:return 0
flag=True
slower,faster=0,1
while faster<len(nums):
if nums[slower]!=nums[faster]:
slower+=1
nums[slower]=nums[faster]
flag=True
else:
if flag:
slower+=1
nums[slower]=nums[faster]
flag=False
faster+=1
return slower+1
测试用例
def removeDuplicates(nums):
if not nums:return 0
flag=True
slower,faster=0,1
while faster<len(nums):
if nums[slower]!=nums[faster]:
slower+=1
nums[slower]=nums[faster]
flag=True
else:
if flag:
slower+=1
nums[slower]=nums[faster]
flag=False
faster+=1
return slower+1,nums
nums=[0,0,1,1,1,1,2,3,3]
index,result=removeDuplicates(nums)
print(result[:index])