Description
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.
Notes:
If the two linked lists have no intersection at all, return null
.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.
Your code should preferably run in O(n) time and use only O(1) memory.
Credits:Special thanks to @stellari for adding this problem and creating all test cases.
Solution
Two iterations with counting length
先遍歷一遍,計算出兩個list的長度。然后讓長的鏈表的頭指針多走幾步,之后雙指針一起走直到相遇(可能為null)。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int l1 = getLength(headA);
int l2 = getLength(headB);
if (l1 < l2) {
return getIntersectionNode(headB, headA);
}
// make sure l1 >= l1
for (int i = l2; i < l1; ++i) {
headA = headA.next;
}
while (headA != headB) { // iterate until two list meet
headA = headA.next;
headB = headB.next;
}
return headA;
}
private int getLength(ListNode head) {
int len = 0;
while (head != null) {
++len;
head = head.next;
}
return len;
}
}
Two iterations without counting length
其實沒有必要計算list length,只需要排除掉長度差距即可,可以在第一遍遍歷時如果走到null則切換到另一個list head,這樣兩個指針就可以到同一個起跑線了。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode p = headA;
ListNode q = headB;
while (p != q) {
p = p != null ? p.next : headB;
q = q != null ? q.next : headA;
}
return p;
}
}
Follow-up: How to detect if two linked lists have intersection?
其實比原題目簡單,因為只需要返回boolean即可,基本有下面幾種做法:
- 將ListA的所有節(jié)點存入HashSet中,然后遍歷ListB,看是否有重合。
- 兩個鏈表如果相交,tail node一定相同。那么可以找到tailA和tailB,比較是否相等即可。
但是這里有一個坑。如果input list有環(huán)怎么辦?這樣就找不到tail了。這種情況下,需要結(jié)合HashSet + findTail兩種做法,對于listB來說,find tail的同時查詢HashSet中是否已經(jīng)有該節(jié)點,如果有那么當前節(jié)點即為偽tail;否則將節(jié)點加入到HashSet中。
遍歷listB時也要維護listB的HashSet,如果listB已經(jīng)遍歷一圈還沒有遇到和listA的intersection,即為不相交。