題目
編寫一個程序,找到兩個單鏈表相交的起始節點。
如下面的兩個鏈表:
在節點 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 個節點。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists
分析
有幾種方式,比較容易想到是當然是暴力法了。
- 第一種方式,暴力法,a不動,b動;a動一下,b動全部。挨個比較O(N2)的解法
- 第二種方式,hashmap解法,循環一遍a鏈表,將其加入到hashmap裏。然後在循環b鏈表,挨個檢查,是否有在map裏。O(M+N)的時間複雜度,O(N)的空間複雜度。
- 第三種方式,先行法,A和B相交,其實相交的後半段是一樣長的,不同的就是前半段。那麼如果我們能讓A和B通過移動其中的長的,將其向前先走幾步。如圖中B比A長1個節點,讓B先走一步,然後A和B一塊走,就能一起到達相交節點。如果沒有相交,則走到頭就會發現了。
- 第四種方式,雙指針法,與上個檢測環的交點類似,如何讓A和B彌補長度上的差距呢?讓A走完再走B的開頭走,B走完再走A的開頭走,這樣A和B的移動步數就都是A+B裏,如果有交點,就會一起到達了。
解法
以下是雙指針解法。第三種的先行法,如果在鏈表有長度時候,將只需要O(N)就能判定,而雙指針其實是O(2N)。
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func getIntersectionNode(headA, headB *ListNode) *ListNode {
if headA == nil || headB == nil {
return nil
}
a, b := headA, headB
for a != b {
if a == nil {
a = headB
} else {
a = a.Next
}
if b == nil {
b = headA
} else {
b = b.Next
}
}
return a
}