1. 程式人生 > >Leetcode 160:相交連結串列(超詳細的解法!!!)

Leetcode 160:相交連結串列(超詳細的解法!!!)

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

如下面的兩個連結串列**:**

在節點 c1 開始相交。

示例 1:

輸入: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:

輸入: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:

輸入: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。

注意:

  • 如果兩個連結串列沒有交點,返回 null.
  • 在返回結果後,兩個連結串列仍須保持原有的結構。
  • 可假定整個連結串列結構中沒有迴圈。
  • 程式儘量滿足 O(n) 時間複雜度,且僅用 O(1) 記憶體。

解題思路

最簡單的做法就是先將A中的節點新增到set中,然後遍歷B中的節點,判斷遍歷到的節點是不是在set中已經存在了,如果存在的話,那麼這個就是交點。

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
nodes = set() while headA: nodes.add(headA) headA = headA.next while headB: if headB in nodes: return headB headB = headB.next return None

但是這種做法我們的空間複雜度就是O(n)。如果使用O(1)的空間複雜度該怎麼做呢?

如果我們將連結串列拉直,然後按照A+BB+A拼在一起。

規律已經很明顯了,我們只需要將AB中節點比較,如果為空,我們就將AB接到對應的節點後繼續遍歷,最後一定會出現相同節點的情況(如果相交的話)。

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        n1, n2 = headA, headB
        while n1 != n2:
            n1 = n1.next if n1 else headB
            n2 = n2.next if n2 else headA
            
        return n1

reference:

https://leetcode.com/problems/intersection-of-two-linked-lists/discuss/49785/Java-solution-without-knowing-the-difference-in-len!

我將該問題的其他語言版本新增到了我的GitHub Leetcode

如有問題,希望大家指出!!!