一、题目
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
listA - 第一个链表
listB - 第二个链表
skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists
二、解题思路
方法一:
双指针从头遍历解法,每次移动一个位置,当一个指针指向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) {
if (headA==null || headB==null) {
return null;
}
ListNode p1 = headA, p2 = headB;
while(p1!=p2) {
// p1为null时指向另一个链表headB,否则指向下一个节点,p2同理
p1=p1==null?headB:p1.next;
p2=p2==null?headA:p2.next;
}
return p1;
}
}
方法二:
先计算出2个链表的长度只差为n,然后将较长的链表跳过n个节点,较长链表从 n+1 个节点开始移动,短的链表从头开始移动,节点相等之处,就是交叉的节点。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA==null || headB==null) {
return null;
}
int lenA =0,lenB=0,diff=0;
ListNode p1=headA,p2=headB;
while(p1!=null){
lenA++;
p1=p1.next;
}
while(p2!=null){
lenB++;
p2=p2.next;
}
// p1用来保存较长的链表,计算两链表长度的差值diff
if (lenA < lenB) {
p1 = headB;
p2 = headA;
diff=lenB-lenA;
}else {
p1 = headA;
p2 = headB;
diff=lenA-lenB;
}
for (int i=0;i<diff;i++) {
// 较长的链表跳过diff个节点开始移动
p1 = p1.next;
}
// 如果2个链表不相交,直到一个链表指针指向null,就结束循环
while(p1!=null && p2!=null) {
if (p1==p2) {
return p1;
}
p1 = p1.next;
p2 = p2.next;
}
return null;
}
}