Problem
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.
题目
编写一个程序找到两个单链表开始相交的节点。
如下两个链表:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在c1处开始相交。
注意:
- 如果两个链表没有交集,返回null。
- 在函数返回后,链表必须保留原来的结构。
- 假定整个链表结构中没有循环。
- 代码的时间复杂度最好是O(n),空间复杂度最好是:O(1)。
题解
题意
intersection:
intersection的含义需要理解的透彻一点,真正理解intersection的含义,这道题写起来会比较轻松一点。
intersection字面上就是相交的意思,在这道题里面意味着,一旦两条链表相交,那么这两条链表从相交的节点开始后面的所有的节点都是相同的,不会再出现相交后再分开的情况。
如下这种情况不会出现:
A: a1 → a2 a4
↘ ↗
c1
↗ ↘
B: b1 → b2 → b3 b5
下面这两段话是论坛里的讨论,讲的很清楚。
In general, you cannot tell whether two linked lists are intersected solely based on the values of the nodes. For the purpose of online judging, however, we deliberately assign a unique value for each node. So in our test cases, the value can be regard as sort of a unique id for the node; if both linked lists have a node with the same value, then this node must be part of their intersection.
In your example, it seems that the lists merge first at 3, then detach from each other, then merge again at 5. This is not possible because after two lists merge, they can never branch out again. They can be: {2, 3, 4, 5} / {9, 3, 4, 5} (intersect at 3) or {2, 3, 7, 5} / {9, 1, 4, 5} (intersect at 5).
解题思路
根据题意如下思路解题:
- 对于两条长度相等的链表可从第一个节点依次比较,遇到相交点返回该节点即可。
- 对于两条长度不等的链表,可以先对长链表进行截断,截取长链表后面和短链表相等部分,再重复上一个步骤即可。
代码
public class _160_Intersection_of_Two_LinkedLists {
/**
* Leetcode提示的数据结构
* @author zhao
*
*/
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public ListNode equalLengthOperation (ListNode pa, ListNode pb) {
while(pa != null) {
if(pa == pb) {
return pa;
}
else {
pa = pa.next;
pb = pb.next;
}
}
return null;
}
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lenDiff = len(headA) - len(headB);
ListNode pa = headA;
ListNode pb = headB;
if(pa == null || pb == null)
return null;
//如果等长
else if(lenDiff == 0) {
return equalLengthOperation(pa,pb);
}
//如果A比B长
else if(lenDiff > 0) {
for(int i = 0; i< lenDiff; i++)
pa = pa.next;
return equalLengthOperation(pa,pb);
}
//如果B比A长
else if(lenDiff < 0) {
for(int i = 0; i< (0 - lenDiff); i++)
pb = pb.next;
return equalLengthOperation(pa,pb);
}
else
return null;
}
/**
* 计算链表的长度
* @param node
* @return
*/
private static int len(ListNode node) {
int len = 0;
ListNode tmp = node;
while(tmp != null) {
len++;
tmp = tmp.next;
}
return len;
}
}