题目
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
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.
答案1:
HashSet。先把一条链放入HashSet,在从另一条链起点开始遍历,第一个重复节点就是交汇点。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
HashSet<ListNode> set = new HashSet<ListNode>();
ListNode p = headA;
do {
set.add(p);
p = p.next;
} while (p != null);
p = headB;
while (p != null && !set.contains(p)) {
p = p.next;
}
return p;
}
答案2:
先求得每条链的长度。将长的链next至和短链相同长度,然后“齐头并进”。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode a = headA, b = headB;
int numA = 1, numB = 1;
while (a.next != null) {
numA++;
a = a.next;
}
while (b.next != null) {
numB++;
b = b.next;
}
if (a != b) return null;
a = headA;
b = headB;
while (numA > numB) {
a = a.next;
numA--;
}
while (numB > numA) {
b = b.next;
numB--;
}
while (a != b) {
a = a.next;
b = b.next;
}
return a;
}
答案三:
一个指针从A开头遍历至结尾,转B;另一个指针从B开头遍历至结尾,转A。len(A) + len(B) == len(B) + len(A),从而保证到达交汇点前“齐头并进”。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode a = headA, b = headB;
//关键是要保持“齐头并进”
while (a != b) {
a = (a == null ? headB : a.next);
b = (b == null ? headA : b.next);
}
return a;
}