编写一个程序,找到两个单链表相交的起始节点。
LeetCode-160.相交链表
思路:
1.如果headA或headB为空 则无交点
2.设定两个指针a和b,a从headA(a1)开始,b从headB(b1)开始
3.两者同时后移,若a移到headA链表尾(c3)则a换路从headB(b1)开始接着后移;若b移到headB链表尾(c3)则b换路从headA(a1)开始接着后移
4.后移过程中,若出现a和b指向同一节点,则该节点为交点;若a和b皆换路且都到达链表尾部,则无交点
原理
虽然题目中强调了链表中不存在环,但是我们可以用环的思想来做,我们让两条链表分别从各自的开头开始往后遍历,当其中一条遍历到末尾时,我们跳到另一个条链表的开头继续遍历。两个指针最终会相等,而且只有两种情况,一种情况是在交点处相遇,另一种情况是在各自的末尾的空节点处相等。为什么一定会相等呢,因为两个指针走过的路程相同,是两个链表的长度之和,所以一定会相等。这个思路比较巧妙,而且更重要的是代码写起来特别的简洁。
难点
因为按照换路思想两个指针遍历的总路程相等,所以换路后两个指针对应元素最终肯定会相等,相等有两种情况:1、两个指针在交点处相遇所指的元素对应相等,此时返回一个元素值;2、若无交点,两个指针最终都指向空(此情况也算是相等),此时返回null;
解法1
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null) return null; //先判空
ListNode a=headA; //A链表第一个元素给a
ListNode b=headB;
while(a!=b){ //在a不等于b的情况下
a=(a!=null)?a.next:headB; //利用三目运算符,若当前a不为空时a=a.next否则换路
b=(b!=null)?b.next:headA;
}
return a; //如果a=b时,返回a/b都行
}
}
解法2
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null) return null; //先判空
ListNode pa=headA; //A链表第一个元素给a
ListNode pb=headB;
boolean ispachange=false; //给定换路标记,默认为false
boolean ispbchange=false;
while(pa!=null&&pb!=null){
if(pa==pb){
return pa;
}
pa=pa.next;
pb=pb.next;
if(ispachange&&ispbchange&&pa==null&&pb==null){ //如果换路了并且到达尾部则说明没有相交
break;
}
if(pa==null){
pa=headB; //如果pa指向空则换路
ispachange=true; //标记换路
}
if(pb==null){
pb=headA;
ispbchange=true;
}
}
return null;
}
}