【科学刷题】完全吃透所有链表题

1. 链表反转

1.1 完全反转

剑指 Offer 24. 反转链表

  • 迭代
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        p = head
        pre = None
        while p:
            aft = p.next
            p.next = pre
            pre = p
            p = aft
        return pre
  • 递归

递归法就记一张图 — 递归反转链表的一部分

1->2->3->^
1->2<-3
   |->^
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head
        last = self.reverseList(head.next)
        head.next.next = head
        head.next = None
        return last

1.2 部分反转

92. 反转链表 II

结合对1.1递归法的学习,将后继None替换成本场景的successor,我们看看commits:

在这里插入图片描述

class Solution:
    successor = None

    def reverseN(self, head: ListNode, N=inf) -> ListNode:
        if N == 1 or head is None or head.next is None:
            self.successor = head.next
            return head
        last = self.reverseN(head.next, N - 1)
        head.next.next = head
        head.next = self.successor
        return last

    def reverseBetween(self, head: ListNode, left: int, right: int) -> ListNode:
        if left == 1:
            return self.reverseN(head, right)
        head.next = self.reverseBetween(head.next, left - 1, right - 1)
        return head

1.3 K个一组反转

25. K 个一组翻转链表

class Solution:
    def reverse(self, a, b):
        # 相当于左开右闭,例如k=2,
        #  1->2->3
        # a↑    b↑
        # 最后返回是的 2->1->∅
        pre = None
        p = a
        while p != b:
            aft = p.next
            p.next = pre
            pre = p
            p = aft
        return pre

    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
        a = b = head
        # 循环体写错 (老错误)
        for _ in range(k):
            if b is None:
                return head
            b = b.next
        new_head = self.reverse(a, b)
        # 把 a 写成了 new_head
        a.next = self.reverseKGroup(b, k) # b 写错 (老错误)
        return new_head

2. 链表相交 + 链表找环

本文还有大量没有考虑到的情况,可以看相关博客

数据结构及算法:链表相关(如何判断单链表是否存在环、找出入环点、链表相交等问题)

寻找两个链表相交节点方法(可以是有环链表)

求两个链表的相交点(含链表带环情况)

插图出自"求两个链表的相交点(含链表带环情况)",本文2.1 普通相交讨论case 02.2 普通有环讨论case 12.3 相交有环讨论case 2, case 32.3 相交有环对4种情况都做了总结,考虑了所有边界条件

2.1 普通相交

160. 相交链表

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        a, b = headA, headB
        while a != b:
            a = a.next if a else headB
            b = b.next if b else headA
        return a

1650. 二叉树的最近公共祖先 III

class Solution:
    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
        a, b = p, q
        while a != b:
            a = a.parent if a else q
            b = b.parent if b else p
        return a

2.2 普通有环

2.2.1 判断是否有环

141. 环形链表

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                return True
        return False

2.2.2 找出环的入口

142. 环形链表 II

如果快慢指针是在写不出来,可以用hash表来写,就是空间复杂度会变成 O ( N ) O(N) O(N)

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        vis = {
   }
        p = head
        while p:
            id_ = id(p)
            if id_ in vis:
                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值