LeetCode 160: 相交鏈表 Intersection of Two Linked Lists

愛寫Bug(ID:iCodeBugs)node

編寫一個程序,找到兩個單鏈表相交的起始節點。學習

Write a program to find the node at which the intersection of two singly linked lists begins.3d

以下面的兩個鏈表**:**指針

img

在節點 c1 開始相交。code

示例 1:blog

img

輸入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
輸出:Reference of the node with value = 8
輸入解釋:相交節點的值爲 8 (注意,若是兩個列表相交則不能爲 0)。從各自的表頭開始算起,鏈表 A 爲 [4,1,8,4,5],鏈表 B 爲 [5,0,1,8,4,5]。在 A 中,相交節點前有 2 個節點;在 B 中,相交節點前有 3 個節點。

示例 2:**ip

img

輸入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
輸出:Reference of the node with value = 2
輸入解釋:相交節點的值爲 2 (注意,若是兩個列表相交則不能爲 0)。從各自的表頭開始算起,鏈表 A 爲 [0,9,1,2,4],鏈表 B 爲 [3,2,4]。在 A 中,相交節點前有 3 個節點;在 B 中,相交節點前有 1 個節點。

示例 3:**內存

img

輸入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
輸出:null
輸入解釋:從各自的表頭開始算起,鏈表 A 爲 [2,6,4],鏈表 B 爲 [1,5]。因爲這兩個鏈表不相交,因此 intersectVal 必須爲 0,而 skipA 和 skipB 能夠是任意值。
解釋:這兩個鏈表不相交,所以返回 null。

注意:get

  • 若是兩個鏈表沒有交點,返回 null.
  • 在返回結果後,兩個鏈表仍須保持原有的結構。
  • 可假定整個鏈表結構中沒有循環。
  • 程序儘可能知足 O(n) 時間複雜度,且僅用 O(1) 內存。 相交鏈表

Notes:同步

  • If the two linked lists have no intersection at all, return null.
  • The linked lists must retain their original structure after the function returns.
  • You may assume there are no cycles anywhere in the entire linked structure.
  • Your code should preferably run in O(n) time and use only O(1) memory.

解題思路:

注意:長鏈表比短鏈表多出的長度是無需比較的

剛開始我是想着直接從兩個鏈表末尾向前遍歷對比節點是否相等,後面纔看到是單鏈表。可是依然有不少的解題方法:

  • 哈希表:把一個鏈表的節點先存儲在哈希表,遍歷另外一個節點並判斷該節點地址是否在哈希表中出現過若是出現過,輸出該節點。須要佔用額外空間 O(n)。

若是按要求在 O(1) 空間複雜度解題,最容易想到的就是:遍歷鏈表獲得鏈表長度,計算雙鏈表差值,長鏈表減去差值獲得的剩下的鏈表與短鏈表長度相等,而後開始比較地址。,當遇到第一個節點地址相同時即爲所求。

這個原理簡單,可是代碼太冗長了,咱們來看另外一種更優雅的解法,看圖幫助理解:

160_Intersection_of_TwoLinkedLists.png

定義兩個指針curA、curB分別從鏈表A、B開始遍歷鏈表,此時最早遇到空節點(到達末尾)的鏈表即爲短鏈表。

curA、curB走過的長度均爲LenA

此時將curA指向鏈表 B (長鏈表)的頭節點,curB 不變。兩個指針開始第二段遍歷,直到 curB 遇到空節點(長鏈表到達末尾)。

此時 curB 走完整個長鏈表,走的第二段長度就是差值 L。CurA 從長鏈表頭節點開始,與 curB 同步,其走的第二段長度一樣是差值 L。

此時 curA 在長鏈表 剩餘未遍歷的節點長度是:LenB - L = LenA

此時將 curB 指向鏈表A的頭節點,即將遍歷鏈表A 的長度爲 LenA ,則curA、curB剩餘即將遍歷的長度即爲本來須要比較的長度。

開始第三段遍歷,遇到第一個相同節點時返回便可。

代碼:

Java:

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        ListNode curA = headA;
        ListNode curB = headB;
        while (curA != curB) {
            curA = curA == null ? headB : curA.next;
            curB = curB == null ? headA : curB.next;
        }
        return curA;
    }
}

Python:

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        if not headA or not headB:
            return None
        curA , curB = headA , headB
        while curA != curB:
            curA = curA.next if curA else headB
            curB = curB.next if curB else headA
        return curA

歡迎關注公衆號一塊兒學習:愛寫Bug

愛寫Bug.png

相關文章
相關標籤/搜索