0
点赞
收藏
分享

微信扫一扫

单链表套路总结

yongxinz 2022-02-15 阅读 46

21.合并两个有序列表

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
采用一个空节点,没什么好说的。

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        dummy = ListNode()
        p = dummy
        while l1 and l2:
            if l1.val < l2.val:
                dummy.next = l1
                dummy = dummy.next
                l1 = l1.next
            else:
                dummy.next = l2
                dummy = dummy.next
                l2 = l2.next
        while l1:
            dummy.next = l1
            dummy = dummy.next
            l1 = l1.next
        while l2:
            dummy.next = l2
            dummy = dummy.next
            l2 = l2.next
        return p.next

23. 合并K个升序列表

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        import heapq
        heapMin = []
        for ls in lists:
            while ls:
                heapq.heappush(heapMin, ls.val)
                ls = ls.next
        dummy = ListNode(0)
        p = dummy
        while heapMin:
            p.next = ListNode(heapq.heappop(heapMin))
            p = p.next
        return dummy.next

使用最小堆,将所有列表的所有元素进行排序,然后依次放入链表中即可。
堆的使用:

import heapq
heapq.heappush(heapMin, ls.val)
heapq.heappop(heapMin)

19.删除链表的倒数第N个节点

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

尝试使用一次扫描实现。

可以先让p1走k步,现在的p1只需要再走n-k步就能走到链表末尾。这时p2指向头节点,往后走,当p1走到末尾,p2就走到了倒数第k个节点。
这样就得到了倒数第k个节点。

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        def findFromEnd(head: ListNode, k: int):
            p1 = head
            while k:
                p1 = p1.next
                k = k - 1
            p2 = head
            while p1:
                p2 = p2.next
                p1 = p1.next
            return p2
        dummy = ListNode(0)
        dummy.next = head
        x = findFromEnd(dummy, n+1)
        x.next = x.next.next
        return dummy.next

不过注意我们又使用了虚拟头结点的技巧,也是为了防止出现空指针的情况,比如说链表总共有 5 个节点,题目就让你删除倒数第 5 个节点,也就是第一个节点,那按照算法逻辑,应该首先找到倒数第 6 个节点。但第一个节点前面已经没有节点了,这就会出错。

141.环形链表 142.环形链表II

每当慢指针slow前进一步,快指针fast就前进两步。

如果fast最终遇到空指针,说明链表中没有环;如果fast最终和slow相遇,那肯定是fast超过了slow一圈,说明链表中含有环。
在这里插入图片描述
可以看到,当快慢指针相遇时,让其中任一个指针指向头节点,然后让它俩以相同速度前进,再次相遇时所在的节点位置就是环开始的位置。

我们假设快慢指针相遇时,慢指针slow走了k步,那么快指针fast一定走了2k步.
fast一定比slow多走了k步,这多走的k步其实就是fast指针在环里转圈圈,所以k的值就是环长度的「整数倍」。
假设相遇点距环的起点的距离为m,那么结合上图的 slow 指针,环的起点距头结点head的距离为k - m,也就是说如果从head前进k - m步就能到达环起点。

巧的是,如果从相遇点继续前进k - m步,也恰好到达环起点。因为结合上图的 fast 指针,从相遇点开始走k步可以转回到相遇点,那走k - m步肯定就走到环起点了:
所以,只要我们把快慢指针中的任一个重新指向head,然后两个指针同速前进,k - m步后一定会相遇,相遇之处就是环的起点了。

    def detectCycle(self, head: ListNode) -> ListNode:
        slow = head
        fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if fast == slow:
                break
        if fast == None or fast.next== None:
            # 说明没有环
            return None
        # 重新指向头节点
        slow = head
        # 快慢指针同步,相交点就是环起点 
        while slow != fast:
            fast = fast.next
            slow = slow.next
        return slow

876. 链表的中间节点

每当慢指针slow前进一步,快指针fast就前进两步,这样,当fast走到链表末尾时,slow就指向了链表中点。

class Solution:
    def middleNode(self, head: ListNode) -> ListNode:
        slow = head
        fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        return slow

160. 相交链表

给你输入两个链表的头结点headA和headB,这两个链表可能存在相交。

如果相交,你的算法应该返回相交的那个节点;如果没相交,则返回 null。
所以,我们可以让p1遍历完链表A之后开始遍历链表B,让p2遍历完链表B之后开始遍历链表A,这样相当于「逻辑上」两条链表接在了一起。

如果这样进行拼接,就可以让p1和p2同时进入公共部分,也就是同时到达相交节点c1:
那你可能会问,如果说两个链表没有相交点,是否能够正确的返回 null 呢?

这个逻辑可以覆盖这种情况的,相当于c1节点是 null 空指针嘛,可以正确返回 null。

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        p1 = headA
        p2 = headB
        while p1!= p2:
            if p1 == None:
                p1 = headB
            else:
                p1 = p1.next
            if p2 == None:
                p2 = headA
            else:
                p2 = p2.next
        return p1
举报

相关推荐

0 条评论