Leetcode 160. 相交链表

287 阅读2分钟

原题链接: 160. 相交链表 - 力扣(Leetcode)

tag: 双指针, 链表.

一. 题目

给你两个单链表的头节点 headA 和 headB , 请你找出并返回两个单链表相交的起始节点. 如果两个链表不存在相交节点, 返回 null .

图示两个链表在节点 c1 开始相交 :

image.png

题目数据 保证 整个链式结构中不存在环.

注意, 函数返回结果后, 链表必须 保持其原始结构 .

二. 题解

本题采用双指针的方法解题.

image.png

ListNode* pA = headA;

image.png

ListNode* pB = headB;

image.png

pApB 没有相遇时.

pA != pB

image.png

更新 pA 指针.

pA = pA->next;

image.png

更新 pB 指针.

pB = pB->next;

image.png

pApB 仍未相遇.

pA != pB

image.png

重复这一步骤.

image.png

重复这一步骤.

image.png

重复这一步骤.

image.png

重复这一步骤.

pA == nullptr

pA 遍历完 A 链表.

image.png

更新 pA 指针, pA 开始遍历 B 链表.

pA = headB;

image.png

更新 pB 指针.

pB = pB->next;

image.png

pApB 仍未相遇.

pA != pB

image.png

更新 pA 指针.

pA = pA->next;

image.png

pB == nullptr

pB 遍历完 B 链表.

image.png

更新 pB 指针, pB 开始遍历 A 链表.

pB = headA;

image.png

重复这一步骤.

image.png

重复这一步骤.

image.png

pA == pB

pApB 相遇, 找到两个链表相交的起始节点.

image.png

返回两个链表相交的起始节点.

return pA;

image.png

三. 复杂度分析

时间复杂度: O(M + N), 其中 M 和 N 分别是链表 A 和 B 的长度. pApB 两个指针同时遍历两个链表: 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;    // 返回相交节点
    }
};