【三次過】Lintcode 380. 兩個連結串列的交叉
阿新 • • 發佈:2018-11-08
請寫一個程式,找到兩個單鏈表最開始的交叉節點。
樣例
下列兩個連結串列:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在節點 c1 開始交叉。
挑戰
需滿足 O(n) 時間複雜度,且僅用 O(1) 記憶體。
注意事項
- 如果兩個連結串列沒有交叉,返回
null
。 - 在返回結果後,兩個連結串列仍須保持原有的結構。
- 可假定整個連結串列結構中沒有迴圈。
解題思路:
時間:O(2 * (LenA + LenB)) = O(LenA + LenB)
空間:O(1)
演算法:
- 分別測量兩個連結串列的長度;
- 通過長度比較,令兩個連結串列的頭指標都指向 距離末尾節點距離相同 並且 距離最遠的地方。其實就是讓兩個指標指向離交叉點距離相同的位置;
- 一起挪動兩個指標,知道他們指向同一個節點;
- 返回任意一個指標指向的節點。
/** * Definition for ListNode * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { /** * @param headA: the first list * @param headB: the second list * @return: a ListNode */ public ListNode getIntersectionNode(ListNode headA, ListNode headB) { // write your code here if(headA == null || headB == null) return null; int lenA = measureLength(headA); int lenB = measureLength(headB); ListNode nodeA = headA; ListNode nodeB = headB; //根據兩者長度定比較起始點,使得從起始點開始兩者長度一致 while(lenA < lenB){ lenB--; nodeB = nodeB.next; } while(lenA > lenB){ lenA--; nodeA = nodeA.next; } //按順序比較節點 while(nodeA != nodeB){ nodeA = nodeA.next; nodeB = nodeB.next; } return nodeA; } private int measureLength(ListNode head){ int len = 0; ListNode node = head; while(node != null){ len++; node = node.next; } return len; } }