先来个最普通的,原地数组去重:
26. 删除有序数组中的重复项
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
if not nums: return 0
# 定义快慢指针,一前一后初始化
slow, fast = 0, 1
while fast < len(nums):
# 两个指针指的数不一样的话就让慢指针挪动一下,然后更新成快指针的值,快指针每次前进一步
if nums[fast] != nums[slow]:
slow += 1
nums[slow] = nums[fast]
fast += 1
return slow + 1
他的升级版:
80. 删除有序数组中的重复项 II
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
if len(nums)<2: return len(nums)
slow, fast = 2,2
while fast < len(nums):
if nums[fast] != nums[slow-2]:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
可以把上面两题进行统一,就是如果最多保留K个重复项的情况下:
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
def solve(k): # 最多保留k位相同数字
slow = 0 # 慢指针从0开始
for fast in nums: # 快指针遍历整个数组
# 检查被保留的元素nums[slow−k]是否和当前待检查元素fast相同
if slow < k or nums[slow - k] != fast:
nums[slow] = fast
slow += 1
return slow # 从nums[0]到nums[slow−1]的每个元素都不相同
return solve(2)
再看一道不一样的难一些的:
316. 去除重复字母
class Solution:
def removeDuplicateLetters(self, s) -> int:
stack = []
seen = set()
remain_counter = collections.Counter(s)
for c in s:
if c not in seen:
while stack and c < stack[-1] and remain_counter[stack[-1]] > 0:
seen.discard(stack.pop())
seen.add(c)
stack.append(c)
remain_counter[c] -= 1
return ''.join(stack)
再看一道差不多的:
27. 移除元素
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
slow, fast = 0,0
while fast < len(nums):
# 快指针在前面跑,遇到目标元素就让慢指针跳过
if nums[fast] != val:
nums[slow] = nums[fast]
slow += 1
fast += 1
return slow
还有:
283. 移动零
这一题和上面那一题就很想,只需要在循环结束之后把slow后面的元素全部置为0即可:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
slow, fast = 0, 0
length = len(nums)
while fast < length:
if nums[fast] != 0:
nums[slow] = nums[fast]
slow += 1
fast += 1
# 至此slow后面的就都应该赋值为0了
for i in range(slow,length):
nums[i] = 0
return nums
按照这个思路我们其实可以一步到位,因为slow后面全部是我们不要的那些元素,只要我们在元素赋值的时候改为交换元素值就可以了:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
slow, fast = 0, 0
length = len(nums)
while fast < length:
if nums[fast] != 0:
nums[slow], nums[fast] = nums[fast], nums[slow]
slow += 1
fast += 1
return nums
此种思路拿来做删除链表中的重复元素也是一样的:
83. 删除排序链表中的重复元素
需要注意最后对慢指针的处理:
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
if not head:return None
fast,slow = head,head
while fast:
#不相等就更新慢指针,否则快指针继续往前走探路,直到探到与慢指针不一样的值,或者全部探完了
if fast.val != slow.val:
#删除重复元素
slow.next = fast
#两个指针继续同步
slow = fast
fast = fast.next
#先头兵指向空了,慢指针不管有没有指向空,都需要指向空,解决最后几个元素是重复元素的情况
slow.next = None
return head