80.删除有序数组中的重复项II
🕯 80.删除有序数组中的重复项II
给你一个有序数组 nums
,请你**
原地
** 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
思路
基本思想
本题与 26.删除有序数组中的重复项 有些类似,只不过每种类型的元素不是只保留一个,而是最多保留两个,这个要求包含两层意思,第一个意思是本来就只出现一次或者两次的数据直接留下不删除,出现三次以上的数据需要删除多余的,只保留两次
这种从数组中删除不符合要求元素的题目,一般使用快慢指针来解题,需要明确的是,慢指针在题中代表的含义是当前需要保留的元素的最后位置。对于本题来说,当元素出现次数小于等于两次时就可以留下,如何使用代码表示当前元素出现次数小于等于两次呢?
可以考虑极端情况,当前元素是第三次出现,那么说明前两次已经保存起来了,现在slow慢指针指向的位置就是这个第三次出现的位置,当前元素不能保留,也就是当nums[fast]==nums[slow-2]
的时候,这个元素不能保留,-2的原因是因为当前的元素需要保留最多两个,当前slow的位置前面有两个重复的元素时,当前slow的位置就可以覆盖,否则就不能覆盖
最开始的想法是,当当前元素出现第一次或者出现第二次时,都可以留下,判断的条件是:
|
|
但是当nums=[1,1,1,2,2,3]
时,第一个2保留之后,nums变为[1,1,2,2,2,3],此时slow在加粗的位置,fast在斜体的位置,使用上面的判断条件,fast处的元素无法保留,其实按照题意应该保留
使用nums[fast]!=nums[slow-2]
这个条件时,一定能确保slow前面每种元素最多可以保留两个
核心就是明白slow代表当前需要保留的元素的最后的位置,fast是当前第一个待判断的元素
此处补充一下
26. 删除有序数组中的重复项
的解题思路,为了将每种元素保留一次,相当于每一种元素头一次出现时就需要记录一下,所以判断条件是nums[fast]!=nums[fast-1]
就需要保留当前元素
执行流程
从第三个元素开始,判断每个元素是否应该保留
如果当前这种元素已经保留了两个了,那么就不需要再保留了
如果当前元素还没有保留够两个,就尝试保留,没有够两个有两种情况:
- 当前元素第一次出现,需要保留
- 当前元素第二次出现,需要保留
判断当前元素是否保留够两个的条件是看slow之前有没有两个当前元素,只要不够两个元素就可以保留
返回有效元素的长度
代码
根据以上分析,得出以下代码:
|
|
总结
总结起来需要注意两点:
- slow代表的是当前以保存的所有元素的最后位置
- 每种元素最多可以保留两个
判断当前元素是否需要保留就是看slow前有没有两个以上的当前元素,也就是看slow退后两个位置处的元素与当前元素是否相等,不相等代表当前元素的出现次数少于2,可以保留,相等代表当前元素的出现次数大于2,不能保留,所以核心就是看**nums[fast]和nums[slow-2]**的关系