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.
思路分析:这题考察链表操作,首先要正确理解题意。如果两个链表有intersection,那么最后一个node必然是同一个node,否则就是没有intersection。然后如果我们已经知道两个链表有intersection,如果去找第一个交叉的node呢?最直接的方法是用两个指针同时在两个链表走,但是如何保证它们可以同时到达那个首个交叉的node呢?我们可以让这两个指针的起点不同,保证他们同时走的时候,到达首个交叉的node的距离相等。于是我们想到利用两个链表的长度之差|len1 - len2|.如果len1 > len2,那么就先让pa先走|len1 - len2|步,然后pa和pb一起走,必然同时到达首个交叉的node。对于len1 <= len2的情况,同理可以分析。
AC Code
/**
* 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) {
if(headA == null || headB == null) return null;
ListNode pa = headA;
ListNode pb = headB;
int lenA = 1;
int lenB = 1;
while(pa.next != null){
pa = pa.next;
lenA++;
}
while(pb.next != null){
pb = pb.next;
lenB++;
}
if(pa != pb) return null; //no intersection
pa = headA;
pb = headB;
int diff = Math.abs(lenA - lenB);
if(lenA > lenB){
while(diff != 0 ){
pa = pa.next;
diff--;
}
} else {
while(diff != 0){
pb = pb.next;
diff--;
}
}
while(pa != pb){
pa = pa.next;
pb = pb.next;
}
return pa;
}
}