目录
题目
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 输出:Intersected at '8' 解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。 从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。 在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
思路
方法一
就是求两个链表交点节点的指针。交点不是数值相等,而是指针相等。
他是链表尾部相交,所以我们需要先得到两个链表的长度。后面为了方便分析判断,链表长的我们让他都为A。
到这里以后我们开始遍历A和B然后找到它的相同节点的头。
方法二
设「第一个公共节点」为 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>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
若两链表 无 公共尾部 (即 c=0) :指针 A , B 同时指向 null 。
因此返回 A 即可。
如链表A+链表B=链表C1
链表B+链表A=链表C2
A -> a1 a2 c1 c2 c3
B -> b1 b2 b3 c1 c2 c3
C1 -> a1 a2 c1 c2 c3 b1 b2 b3 c1 c2 c3
C2 -> b1 b2 b3 c1 c2 c3 a1 a2 c1 c2 c3
此时C1和C2的长度一定相同。 而C1和C2的结尾就一定是相交的链表。
代码
public class Solution {//方法一
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA=headA;//分别定义两个链表的指针
ListNode curB=headB;
int lenA=0,lenB=0;//先暂定他俩的长度都为0,后面再进行判断计算
while(curA!=null){//当指针不为null的时候一直移动指针,然后让长度++,可以计算出A的长度
lenA++;
curA=curA.next;
}
while(curB!=null){//计算链表B的长度
lenB++;
curB=curB.next;
}
curA=headA;//通过上面的操作curA或者B的值改变了,所以需要进行归位再进行下一步操作
curB=headB;
if(lenB>lenA){//为了方便让长一点的链表都为A,所以当B长的时候我们进行交换
int lent=lenA;//先交换长度
lenA=lenB;
lenB=lent;
ListNode curt=curA;//再交换指针
curA=curB;
curB=curt;
}
int gap=lenA-lenB;//这一步是进行上述图解的一步
while(gap-->0){//移动A指针
curA=curA.next;
}
while(curA!=null){//同时移动A和B
if(curA==curB){//找到,返回值
return curA;
}
curA=curA.next;
curB=curB.next;
}
return null;//没找到,返回null
}
}
public class Solution {//方法二
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode curA=headA;
ListNode curB=headB;
while(curA!=curB){//循环寻找
if(curA==null) curA=headB;//找完A了,让他去找B
else curA=curA.next;//还没找完
if(curB==null) curB=headA;//找完B了,让他去找A
else curB=curB.next;//还没找完
}
return curA;//返回找到的
}
}