160. 相交链表

980 阅读1分钟

「这是我参与2022首次更文挑战的第26天,活动详情查看:2022首次更文挑战」。

题目描述

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

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

image.png

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

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

思路分析

从前往后自然很难找到相交的节点,除非用n^2的时间复杂度遍历。但是相交的节点以后所有的节点都会相同,因此我们可以想到如果从后往前来看的话,是不是就可以找到了相交节点。

  • 从后往前,并且声明两个栈,不断遍历将元素写入栈中
  • 不断将栈中元素弹出,直到栈1和栈2弹出的节点不同时,找到上一个被弹出的节点。

主要代码如下:

 while (!(stk1.empty() || stk2.empty())){
    ListNode* idx1 = stk1.top();stk1.pop();
    ListNode* idx2 = stk2.top();stk2.pop();
    if(idx1 -> val != idx2 -> val){
        if(pre == nullptr)return nullptr;
        cout << pre ->val << endl;
        return pre;
    }
    pre = idx1;
}

然而这个方法过不去力扣。。

不过之前做过环形链表的判断倒是给了些优化的灵感,如果两个有相交点,那么可以将A分为Apre,common两部分,将B分为Bpre,common两部分,我们分别设置headA,headB作为起点,只需要让两边都走过

Apre+Bpre+commonApre + Bpre + common

的长度,就可以让两者相遇。

具体实现

 while (tmpA != tmpB) {
            tmpA = tmpA->next;
            tmpB = tmpB->next;
            if(tmpA == nullptr){
                tmpA = headB;
            }
            if(tmpB == nullptr){
                tmpB = headA;
            }
        }

核心代码如上

总结

第一个方法的时间复杂度是O(n),但空间复杂度也是O(n).而第二种时间复杂度不变的同时,空间复杂度确实O(1)。大大节省了空间消耗。