劍指 Offer 52. 兩個連結串列的第一個公共節點
阿新 • • 發佈:2020-07-26
題目描述:
我的題解:
方法一:雙指標法
思路分析:
- 宣告兩個指標p1,p2 分別指向連結串列A、連結串列B。
- 然後分別同時逐結點遍歷
- 當 p1 到達連結串列 headA 的末尾時,重新定位到連結串列 headB 的頭結點;當 p2 到達連結串列 headB 的末尾時,重新定位到連結串列 headA 的頭結點。
- 如此,當它們相遇時,所指向的結點就是第一個公共結點。
(p1 p2可以分別遍歷完兩條連結串列。同時開始,將可以保證同時遍歷結束。又因一旦同時指向第一個相交節點時,剩下的節點數相同;故可以保證p1和p2能同時指向到第一個相交節點(即相遇))
程式碼如下:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) return null; ListNode p1 = headA; ListNode p2 = headB; int change =0; // 重定位到連結串列頭的次數和 while (p1 != p2) { if (p1.next == null) { p1 = headB; // 重定位到另一連結串列頭 change++; } else p1 = p1.next; if (p2.next == null) { p2 = headA; // 重定位到另一連結串列頭 change++; } else p2 = p2.next; if (change > 2) return null; // 兩個指標均已遍歷另一條連結串列了 } return p1; }
方法二:也是雙指標,但先求連結串列長度,再同時移動
思路分析:
- 宣告兩個指標p1,p2 分別指向連結串列A、連結串列B。
- 稍後做一定的處理後 會同時移動兩個指標。
- 此題中,可以保證兩指標最後同時到達連結串列尾,那麼,也就可以保證同時到達相交結點(如果有的話)。
- 那麼,如何保證呢?分別求出兩條連結串列的長度,然後,讓長連結串列對應的指標,先走幾步(步數為多出來的節點數)。
- 做完上一步的處理後,p1和p2再同時移動,便可同時到達連結串列尾,自然就可以保證同時到達相交節點了(如果有的話)。
程式碼如下:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) { ListNode p1 = headA; ListNode p2 = headB; int len1 = getLength(headA); int len2 = getLength(headB); int different = len1 - len2; // 長的指標,先走different步 if (different > 0) { // headA 長 for (int i = different; i > 0; i--) { p1 = p1.next; } } else { // headB長 或 同樣長(different=0,不進for迴圈了) for (int i = -different; i > 0; i--) { p2 = p2.next; } } // 接著, p1,p2同時移動。當 p1 p2指向同一節點時,該節點即為題目所求的相交節點 while (p1!=null && p2!=null && p1 != p2) { p1 = p1.next; p2 = p2.next; } return p1; } private int getLength(ListNode head) { int cnt = 0; for (ListNode tmp = head; tmp !=null ; tmp = tmp.next) { cnt++; } return cnt; }