相交链表
(leetcode 160)
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
两个链表在节点 c1 开始相交:
评测系统 的输入如下(你设计的程序 不适用 此输入): intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0 listA - 第一个链表 listB - 第二个链表 skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数 skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数 评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被视作正确答案 。
sample:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [1,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。
两种方法
方法一哈希集合
cpp sample
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode *> visited;
ListNode *temp = headA;
while (temp != nullptr) {
visited.insert(temp);
temp = temp->next;
}
temp = headB;
while (temp != nullptr) {
if (visited.count(temp)) {
return temp;
}
temp = temp->next;
}
return nullptr;
}
};
方法二双指针
cpp sample
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// 边界判断
if (headA == NULL || headB == NULL) return NULL;
// 设置一个指针 pointA,指向链表 A 的头节点
ListNode *pointA = headA;
// 设置一个指针 pointB,指向链表 B 的头节点
ListNode *pointB = headB;
// 指针 pointA 和 指针 pointB 不断向后遍历,直到找到相交点
// 不用担心会跳不出这个循环,实际上在链表 headA 长度和链表 headB 长度的之和减一
// pointA 和 pointB 都会同时指向 null
// 比如 headA 的长度是 7,headB 的长度是 11,这两个链表不相交
// 那么 pointA 移动了 7 + 11 - 1 次之后,会指向 null
// pointB 移动了 7 + 11 - 1 次之后,也指向 null
// 这个时候就跳出了循环
while (pointA != pointB) {
// 指针 pointA 一开始在链表 A 上遍历,当走到链表 A 的尾部即 null 时,跳转到链表 B 上
if( pointA == NULL){
// 指针 pointA 跳转到链表 B 上
pointA = headB;
}else{
// 否则的话 pointA 不断的向后移动
pointA = pointA->next;
}
// 指针 pointB 一开始在链表 B 上遍历,当走到链表 B 的尾部即 null 时,跳转到链表 A 上
if( pointB == NULL){
// 指针 pointA 跳转到链表 B 上
pointB = headA;
}else{
// 否则的话 pointB 不断的向后移动
pointB = pointB->next;
}
}
// 1、此时,pointA 和 pointB 指向那个相交的节点,返回任意一个均可
// 2、此时,headA 和 headB 不相交,那么 pointA 和 pointB 均为 null,也返回任意一个均可
return pointA;
}
};