链表相交解题思路(leetcode160)

题目描述

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

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

问题分析

链表相交定义

链表相交指的是两个链表在某个节点后面共享相同的节点序列,是节点引用相同,而不是节点值相同。

链表A: [4] -> [1] ----\
                       \
                        [8] -> [4] -> [5] -> NULL
                       /
链表B: [5] -> [0] -> [1] ----/
​
相交起始节点:节点8(注意是节点引用,不是值)

解题思路

方法一:双指针法(优选)

算法思路

核心思想:让两个指针走过的路径长度相同

  1. 指针pA从headA开始,指针pB从headB开始

  2. 当pA到达末尾时,跳到headB继续

  3. 当pB到达末尾时,跳到headA继续

  4. 如果有相交点,两指针必定会在相交点相遇

数学推导
设链表A长度为a,链表B长度为b,相交部分长度为c
​
链表A:a1 -> a2 -> ... -> c1 -> c2 -> ... -> NULL
链表B:b1 -> b2 -> ... -> c1 -> c2 -> ... -> NULL
​
指针pA路径:a1->...->c1->...->NULL->b1->...->c1 (总长度: a + b)
指针pB路径:b1->...->c1->...->NULL->a1->...->c1 (总长度: b + a)
​
两个指针走过相同的路径长度时,会在相交点c1相遇
代码实现
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }
​
        ListNode *pA = headA;
        ListNode *pB = headB;
​
        // 两个指针一直移动,直到相遇或者都为null
        while (pA != pB) {
            // pA达到末尾时跳转到headB,否则移动到下一节点
            pA = (pA == nullptr)? headB : pA->next;
​
            // pB达到末尾时跳转到head,否则移动到下一个节点
            pB = (pB == nullptr)? headA : pB->next;
        }
​
        // 相交点或为null
        return pA; 
    }
};

方法二:哈希表法

算法思路
  1. 遍历链表A,将所有节点存入哈希表

  2. 遍历链表B,检查每个节点是否在哈希表中

  3. 第一个在哈希表中的节点就是相交起始节点

算法流程
步骤1:遍历链表A,存入哈希表
链表A: [4] -> [1] -> [8] -> [4] -> [5] -> NULL
        ↓      ↓      ↓      ↓      ↓
    哈希表: {4, 1, 8, 4, 5}
​
步骤2:遍历链表B,查找相交点
链表B: [5] -> [0] -> [1] -> [8] -> [4] -> [5] -> NULL
        ↓      ↓      ↓      ↓
       不在   不在   不在   找到!
                             ↑
                        相交起始节点
代码实现
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};
​
class Solution {
public:
    // 方法一:哈希表法
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode*> visited;
        
        // 遍历链表A,将所有节点存入哈希表
        ListNode* currA = headA;
        while (currA != nullptr) {
            visited.insert(currA);
            currA = currA->next;
        }
        
        // 遍历链表B,查找第一个在哈希表中的节点
        ListNode* currB = headB;
        while (currB != nullptr) {
            if (visited.find(currB) != visited.end()) {
                return currB;  // 找到相交起始节点
            }
            currB = currB->next;
        }
        
        return nullptr;  // 没有相交点
    }
};

复杂度分析

方法时间复杂度空间复杂度优点缺点
哈希表法O(m+n)O(m)思路直观需要额外空间
双指针法O(m+n)O(1)空间最优,代码简洁需要理解数学原理

其中 m、n 分别是两个链表的长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值