原题链接: 160. 相交链表 - 力扣(Leetcode)
tag: 双指针, 链表.
一. 题目
给你两个单链表的头节点 headA 和 headB , 请你找出并返回两个单链表相交的起始节点. 如果两个链表不存在相交节点, 返回 null .
图示两个链表在节点 c1 开始相交 :
题目数据 保证 整个链式结构中不存在环.
注意, 函数返回结果后, 链表必须 保持其原始结构 .
二. 题解
本题采用双指针的方法解题.
ListNode* pA = headA;
ListNode* pB = headB;
当 pA 和 pB 没有相遇时.
pA != pB
更新 pA 指针.
pA = pA->next;
更新 pB 指针.
pB = pB->next;
pA 和 pB 仍未相遇.
pA != pB
重复这一步骤.
重复这一步骤.
重复这一步骤.
重复这一步骤.
pA == nullptr
pA 遍历完 A 链表.
更新 pA 指针, pA 开始遍历 B 链表.
pA = headB;
更新 pB 指针.
pB = pB->next;
pA 和 pB 仍未相遇.
pA != pB
更新 pA 指针.
pA = pA->next;
pB == nullptr
pB 遍历完 B 链表.
更新 pB 指针, pB 开始遍历 A 链表.
pB = headA;
重复这一步骤.
重复这一步骤.
pA == pB
pA 和 pB 相遇, 找到两个链表相交的起始节点.
返回两个链表相交的起始节点.
return pA;
三. 复杂度分析
时间复杂度: O(M + N), 其中 M 和 N 分别是链表 A 和 B 的长度. pA 和 pB 两个指针同时遍历两个链表: pA 遍历链表 A 一次, 遍历链表 B 的前半部分; pB 遍历链表 B 一次, 遍历链表 A 的前半部分.
空间复杂度: O(1).
四. 代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* pA = headA, * pB = headB; // 定义指针 pA, pB
while (pA != pB) { // 当 pA 和 pB 没有相遇时
pA = pA ? pA->next : headB; // 若 pA 未走到链表 A 尾部, pA 向后走一步; 反之, 则从 headB 开始遍历链表 B
pB = pB ? pB->next : headA; // 若 pB 未走到链表 B 尾部, pB 向后走一步; 反之, 则从 headA 开始遍历链表 A
}
return pA; // 返回相交节点
}
};