递归,迭代在链表中的运用

 

82_删除链表中的重复节点2

83_删除链表中的重复节点1

这两道题的不同点是,82要求删除重复的节点,83式要求保留自身,删除与自身相同的节点。

递归

对于82题

递归结束的条件是与当前节点不同的下一个节点,将重复节点的下一个不一样节点进行递归

class Solution(object):
    def deleteDuplicates(self, head):
        if not head or not head.next:
            return head
        if head.val != head.next.val:
            head.next = self.deleteDuplicates(head.next)
        else:
            move = head.next
            while move and head.val == move.val:
                move = move.next
            return self.deleteDuplicates(move)
        return head

对于83题

因为保留自身,停止递归的条件是当前节点和当前的下下个节点比较,将当前节点的下一个节点进行递归

class Solution(object):
    def deleteDuplicates(self, head):
        if not head or not head.next:
            return head
        if head.val != head.next.val:
            head.next = self.deleteDuplicates(head.next)
        else:
            move = head.next
            while move.next and head.val == move.next.val:
                move = move.next
            return self.deleteDuplicates(move)
        return head

迭代

对于82题

代码中用到了一个常用的技巧:dummy 节点,也叫做 哑节点。它在链表的迭代写法中非常常见,因为对于本题而言,我们可能会删除头结点 head,为了维护一个不变的头节点,所以我们添加了 dummy,让dummy.next = head,这样即使 head 被删了,那么会操作 dummy.next 指向新的链表头部,所以最终返回的也是 dummy.next。

class Solution(object):
    def deleteDuplicates(self, head):
        if not head or not head.next:
            return head
        dummy = ListNode(0)
        dummy.next = head
        pre = dummy
        cur = head
        while cur:
            # 跳过当前的重复节点,使得cur指向当前重复元素的最后一个位置
            while cur.next and cur.val == cur.next.val:
                cur = cur.next
            if pre.next == cur:
                 # pre和cur之间没有重复节点,pre后移
                pre = pre.next
            else:
                # pre->next指向cur的下一个位置(相当于跳过了当前的重复元素)
                # 但是pre不移动,仍然指向已经遍历的链表结尾
                pre.next = cur.next
            cur = cur.next
        return dummy.next

对于83题

使用两个指针 pre 和 cur:pre 节点表示固定一个节点,cur 用于寻找所有跟 pre 值相等的节点。如果 cur.val 等于 pre.val,则删除 cur。在找到不等的 val 之前,pre 不走,只移动 cur。

class Solution(object):
    def deleteDuplicates(self, head):
        if not head: return None
        prev, cur = head, head.next
        while cur:
            if cur.val == prev.val:
                prev.next = cur.next
            else:
                prev = cur
            cur = cur.next
        return head


83——单个节点进行迭代

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def deleteDuplicates(self, head):
        #利用两个指针
        if not head: return None
        cur = head
        while cur.next:
            if cur.val == cur.next.val:
                cur.next = cur.next.next
            else:
               cur = cur.next
        return head


        

哑节点

对于82题

基本思路

几乎所有的链表题目,都具有相似的解题思路。

建一个「虚拟头节点」dummy 以减少边界判断,往后的答案链表会接在 dummy 后面

使用 tail 代表当前有效链表的结尾

通过原输入的 head 指针进行链表扫描

我们会确保「进入外层循环时 head 不会与上一节点相同」,因此插入时机:

head 已经没有下一个节点,head 可以被插入

head 有一下个节点,但是值与 head 不相同,head 可以被插入

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        tail = dummy = ListNode(-1)
        while head:
            if head.next == None or head.val != head.next.val:
                tail.next = head;
                tail = head
            while head.next and head.val == head.next.val:
                head = head.next
            head = head.next
        tail.next = None
        return dummy.next

对于83题

建一个「虚拟头节点」dummy 以减少边界判断,往后的答案链表会接在 dummy 后面

使用 tail 代表当前有效链表的结尾

通过原输入的 head 指针进行链表扫描

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if head == None:
            return None
        dummy = ListNode(-101)
        tail = dummy
        while head:
            if tail.val != head.val:
                tail.next = head;
                tail = tail.next
            head = head.next
        tail.next = None
        return dummy.next 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值