题目描述
输入两个链表,找出他们的第一个公共节点
如下两个链表:
在节点c1开始相交
算法思路
思路一
比较常规的思路:
1.定义两个指针,分别指向两个链表,计算出两个链表的长度
2. 循环两个链表,哪个链表长度比较长,就移动哪个指针,当链表长度相同时,就同时移动两个指针,直到指针指向是同一个节点,或者有一个链表为空
思路二
思路:
- 定义两个指针A和B,分别指向两个链表头headA和headB
- A、B指针同时移动指针,当链表A为空时,指针A指向链表头headB,链表B为空的时候的时候,指针B指向链表头headA,当指针A和指针B相遇的时候,就是要返回的节点
原理:
假设链表A和链表B的公共长度为c,非公共部分的长度分别为La和Lb,当链表A走到链表尾的时候走的步数为 La + c,当链表B走到链表尾的时候走的步数为 Lb + c,然后指针A走链表B的非公共部分Lb,总步数为La + Lb + c,指针B走链表A的非公共部分La,总步数为La + Lb + c,然后两个指针相遇了。
引用爱情的话就是:
我变成你,走过你走过的路;
你变成我,走过我走过的路;
然后我们就相遇了
代码实现
实现一
/**
* 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) {
//定义两个指针
ListNode A = headA;
ListNode B = headB;
//计算出两个链表的长度
int countA = 0;
int countB = 0;
while(A!=null){
countA++;
A = A.next;
}
while(B!=null){
countB++;
B = B.next;
}
//重复指向链表头
A = headA;
B = headB;
//遍历链表
while(A!=null && B!=null){
//移动链表长度比较长的指针
if(countA>countB){
A = A.next;
countA--;
}
else if(countA<countB){
B = B.next;
countB--;
}
//链表长度一样长时,同时移动
else{
//当指针指向同一个节点时返回
if(A==B){
return A;
}
A = A.next;
B = B.next;
}
}
return null;
}
}
实现二
/**
* 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) {
ListNode A = headA;
ListNode B = headB;
while(A!=B){
A = (A!=null)?A.next:headB;
B = (B!=null)?B.next:headA;
}
return A;
}
}