题目[题目及部分解法来源于力扣]
输入两个链表,找出它们的第一个公共节点。
solution one:
先遍历两个链表获得二者长度,如果二者长度不等,且二者长度相差n,则前n个节点一定不存在相交的可能。所以,从n+1个节点进行比较,如果指向相同则返回,无相交则返回null。 public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) return null;
ListNode temp1 = headA;
ListNode temp2 = headB;
int counter1 = 0;
int counter2 = 0;
//获取二者长度
while(temp1 != null){
++counter1;
temp1 = temp1.next;
}
while(temp2 != null){
++counter2;
temp2 = temp2.next;
}
//算出二者长度差,从第n+1个节点开始比较
temp1 = headA;
temp2 = headB;
if(counter1 > counter2){
int distance = counter1 - counter2;
while(distance > 0){
temp1 = temp1.next;
--distance;
}
while(temp1 != null){
if(temp1 == temp2) return temp1;
temp1 = temp1.next;
temp2 = temp2.next;
}
}
else if(counter1 < counter2){
int distance = counter2 - counter1;
while(distance > 0){
temp2 = temp2.next;
--distance;
}
while(temp2 != null){
if(temp2 == temp1) return temp2;
temp1 = temp1.next;
temp2 = temp2.next;
}
}else if(counter1 == counter2){
while(temp1 != null){
if(temp1 == temp2) return temp1;
temp1 = temp1.next;
temp2 = temp2.next;
}
}
return null;
}
或者
public ListNode getIntersectionNode1(ListNode headA, ListNode headB) {
if(headA == null || headB == null) return null;
ListNode temp1 = headA;
ListNode temp2 = headB;
int counter1 = 0;
int counter2 = 0;
while(temp1 != null){
++counter1;
temp1 = temp1.next;
}
while(temp2 != null){
++counter2;
temp2 = temp2.next;
}
temp1 = headA;
temp2 = headB;
if(counter1 == counter2)
{
while(temp1 != null){
if(temp1 == temp2) return temp1;
temp1 = temp1.next;
temp2 = temp2.next;
}
}
else{
temp1 = counter1 > counter2 ? headA : headB;
temp2 = counter1 < counter2 ? headA : headB;
int distance = Math.abs(counter1 - counter2);
while(distance > 0){
temp1 = temp1.next;
--distance;
}
while(temp1 != null){
if(temp1 == temp2) return temp1;
temp1 = temp1.next;
temp2 = temp2.next;
}
}
return null;
}
solution two:
利用哈希集合来存储链表A的节点,由于哈希集合存储元素不相同,故只需要看链表B中节点是否在链表A中出现即可。 public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet<ListNode>();
ListNode temp = headA;
while(temp != null){
set.add(temp);
temp = temp.next;
}
temp = headB;
while(temp != null){
if(set.contains(temp)){
return temp;
}
temp = temp.next;
}
return null;
}
solution three:
方法三:设 [第一个公共节点] 为node,链表headA的节点数量为a,链表headB 的节点数为b,两个链表的公共尾部的节点数量为c,则有:- 头节点 headA 到node前,共有a - c个节点;
- 头节点 headB 到node前,共有b - c个节点;
考虑构建两个节点指针 A , B 分别指向两链表头节点 headA , headB ,做如下操作:
指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:a + (b - c)
指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:b + (a - c)
如下式所示,此时指针 A , B 重合,并有两种情况: a + (b - c) = b + (a - c)
若两链表 有 公共尾部 (即 c > 0c>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
若两链表 无 公共尾部 (即 c = 0 ) :指针 A , B 同时指向 null 。
因此返回 A 即可。
ListNode A = headA, B = headB;
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next : headA;
}
return A;