数组/链表去重

先来个最普通的,原地数组去重:

26. 删除有序数组中的重复项

image-20211022165043698

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

image-20211022175036398

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. 去除重复字母

image-20211022180428719

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. 移除元素

image-20211025113312815

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. 移动零

image-20211025114936796

这一题和上面那一题就很想,只需要在循环结束之后把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. 删除排序链表中的重复元素

image-20211025115730169

需要注意最后对慢指针的处理:

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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值