跳转到主内容
思享编程网:思考分享,玩转编程世界!

链表相交点怎么找?C++浪漫双指针解法,空间O(1)最优!

大家好,我是陆砚码。今天我们来聊聊LeetCode上的一个经典题目:如何找到两个单链表相交的起始节点?

📌 题目描述

给你两个单链表的头节点headAheadB,找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null

进阶挑战:能否设计一个时间复杂度O(N)、仅用O(1)内存的解决方案?

💡 破题思路:走过你走过的路

首先,我们可以排除使用哈希表的方法,因为它的空间复杂度是O(N),不符合题目的要求。那么,我们该如何解决这个问题呢?

关键在于,两个链表相交后的尾部是完全一样的。他们之所以不能同时到达相交点,仅仅是因为前面的独立长度不一样。

于是,我们可以使用一个绝妙的“路程互补”算法:定义两个指针pApB,分别从headAheadB出发。每人每次走一步。当pA走到底(null)时,让它从headB重新开始走。当pB走到底(null)时,让它从headA重新开始走。

为什么这样一定行?假设链表 A 的独立部分长度为 a,链表 B 的独立部分长度为 b,相交部分长度为 c。

pA走过的路程:a+c+b
pB走过的路程:b+c+a

两人走过的总长度完全一样!所以他们最终一定会同时走到那个相交的起点。如果根本不相交(c=0),那他们俩就会在走了 a+b 步之后,双双变成null并在虚无中相遇,代码同样完美成立。

💻 C++ 代码实现 (极简双指针法)

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        // 如果有任何一个链表为空,绝不可能相交
        if (!headA || !headB) return nullptr;

        ListNode *pA = headA;
        ListNode *pB = headB;

        // 只要两人没相遇,就一直走
        while (pA != pB) {
            // pA 走完了,就跳到 B 链表头;否则继续走
            pA = pA == nullptr ? headB : pA->next;
            // pB 走完了,就跳到 A 链表头;否则继续走
            pB = pB == nullptr ? headA : pB->next;
        }

        // 相遇点就是相交节点(如果不相交,这里正好返回 nullptr)
        return pA;
    }
};

这就是我们的解决方案,简单又高效。如果你对这个问题还有疑问,或者想了解更多关于链表的操作,欢迎访问思享编程网(www.sxgpb.com)了解更多内容。

相关文章