1. 題目
輸入兩個鏈表,找出它們的第一個公共節點。
2. 解題思路
詳情見 圖解 雙指針法,浪漫相遇
由於鏈表A和鏈表B長度不一定相同,而二者相交之後的鏈表都是相同的,因此這個題的
難點在於A和B並不同步,所以造成無法比較兩個鏈表中的節點是否相同。
2.1 渣渣思路
發現了上面的關鍵點之後,就寫出了
3.1
的代碼,思路如下:
1)分別遍歷A和B,得到鏈表的長度差diff;
2)讓長的鏈表先走diff步,然後兩個鏈表再同時往下走,這樣兩者就是同步的了,可以進行比較了;
3)返回第一個相同的節點,即第一個交點。
2.2 最佳思路
畫圖更容易理解
兩個指針 p 和 q,分別走A+B 和B+A,總長度是一樣的,所以使得後面p和q是同步走的,就可以進行比較了。
1)p遍歷鏈表A,q遍歷鏈表B;
2)當p遍歷到A的末尾後,再遍歷B;
3)當q遍歷到B的末尾後,再遍歷A;
4)返回第一個交點。
3. 代碼實現
3.1 渣渣解法
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
"""
因爲鏈表的後部是一致的,所以A和B鏈表長度的差異,也就是在公共節點之前那部分的長度差異,只要兩個指針能夠同步前進,就能找到公共節點
難點在於:若兩個鏈表長度不一樣的話,二者不會同時到達第一個公共節點,造成無法比對節點。
"""
length_a = 0
length_b = 0
# 1.遍歷鏈表A,得到鏈表A長度
temp = headA
while temp:
length_a += 1
temp = temp.next
# 2.遍歷鏈表B,得到鏈表B長度
temp = headB
while temp:
length_b += 1
temp = temp.next
# 3. 消去兩個鏈表的差值,使得同步檢查兩個鏈表
difference = length_a - length_b
if length_a > length_b: # 讓headA先走difference步,否則headB先走difference步,使得二者同步
while difference:
headA = headA.next
difference -= 1
else:
difference = -1 * difference
while difference:
headB = headB.next
difference -= 1
while headA:
if headA == headB:
return headA
headA = headA.next
headB = headB.next
return
3.2 最優解法
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
node1, node2 = headA, headB
while node1 != node2:
node1 = node1.next if node1 else headB
node2 = node2.next if node2 else headA
return node1
作者:z1m
鏈接:https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/solution/shuang-zhi-zhen-fa-lang-man-xiang-yu-by-ml-zimingm/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
4. 總結
鏈表中的操作,大致爲一下幾種:
- 雙指針(同速走,倍速走,相差k步走);
- 創建僞節點;
- 改變鏈接,改變元素值;
- 消除長度差。
5. 參考文獻
[1] 劍指offer叢書
[2] 劍指Offer——名企面試官精講典型編程題