相交链表
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
listA - 第一个链表
listB - 第二个链表
skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
哈希表法:
/**
* 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) {
Set <ListNode> hash =new HashSet<>();
ListNode currA =headA;
//把ListA 节点全部存储hash中
while (currA!=null){
hash.add(currA);
currA=currA.next;
}
ListNode currB =headB;
while(currB!=null){
if(hash.contains(currB)){
return currB;
}else{
currB=currB.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) {
if(headA == null || headB == null){
return null;
}
//定义双指针
ListNode Pa=headA;
ListNode Pb=headB;
//只要pa!=pb,就继续走,pa走到ListA末尾,直接转到headB,继续走直到与pb相遇;pb也是同理。因为如果有相交点,则走到相交的距离是一样的。
while(Pa!=Pb){
Pa= Pa==null ? headB : Pa.next;
Pb= Pb==null ? headA : Pb.next;
}
return Pa;
}
}
链表 headA 和 headB 的长度分别是 m和 n。假设链表 headA 的不相交部分有 a 个节点,链表headB 的不相交部分有 b 个节点,两个链表相交的部分有 c个节点,则有 a+c=m,b+c=n。
如果 a=b,则两个指针会同时到达两个链表相交的节点,此时返回相交的节点;
如果 a ! =b,则指针pA 会遍历完链表headA,指针pB 会遍历完链表headB,两个指针不会同时到达链表的尾节点,然后指针 pA 移到链表 headB 的头节点,指针pB 移到链表 headA 的头节点,然后两个指针继续移动,在指针pA 移动了 a+c+b 次、指针pB 移动了 b+c+a 次,之后,两个指针会同时到达两个链表相交的节点,该节点也是两个指针第一次同时指向的节点,此时返回相交的节点。