LeetCode 160題:尋找兩個鏈表的交點(解法巧妙,且其數學原理應該掌握)

題目

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

For example, the following two linked lists:
在這裏插入圖片描述
begin to intersect at node c1.
Example 1:
在這裏插入圖片描述
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
Output: Reference of the node with value = 8
Input Explanation: The intersected node’s value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
Example 2:
在這裏插入圖片描述
Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: null
Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.
注意:

  • 如果不相交,返回null
  • 不能改變輸入鏈表
  • 你可以認爲輸入的鏈表中沒有環路
  • 你的代碼應該儘可能的實現時間複雜度O(n)以及空間複雜度O(1)

解法

常規的解法

依次遍歷鏈表A和B,用集合sa和sb記錄見過的節點,並判斷是否相交.此種算法時間複雜度爲O(n),但是空間複雜度較高.代碼如下:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        na, nb, ni = headA, headB, None
        sa, sb = {na}, {nb}
        while na or nb:
            if na in sb:
                ni = na
                break
            if nb in sa:
                ni = nb
                break
                
            if na:
                na = na.next
                sa.add(na)
            if nb:
                nb = nb.next
                sb.add(nb)
                
        return ni

算法的結果如下:
Runtime: 188 ms, faster than 85.84% of Python online submissions for Intersection of Two Linked Lists.
Memory Usage: 42.9 MB, less than 5.33% of Python online submissions for Intersection of Two Linked Lists.

巧妙且應該掌握的解法

該解法由coordinate_blog進行了清晰的解釋,我在這裏記錄一下.如下圖,鏈表A和B都是由各自黑色的部分和共同的紅色部分組成.
在這裏插入圖片描述
如果將鏈表拉直然後拼成A+B和B+A放在一起,就會成爲下面這個樣子:
在這裏插入圖片描述
最後的紅色部分是對齊了的,所以我們就能在該出通過相等判斷找到相交的位置.注意,沒有相交的情況可以看做在節點None處(最末尾)相交了.代碼如下:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

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

運行結果如下,好像並不是很優秀…:
Runtime: 184 ms, faster than 92.74% of Python online submissions for Intersection of Two Linked Lists.
Memory Usage: 41.8 MB, less than 37.33% of Python online submissions for Intersection of Two Linked Lists.

我將我寫的LeetCode代碼都記錄在了GitHub,歡迎大家去逛逛

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章