跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C算法

相交链表题解与详细分析

解决两个单链表相交节点查找问题。提供两种解法:长度差法和双指针法。长度差法通过计算长度对齐起点后遍历;双指针法利用路径总长相等特性,无需计算长度。两者时间复杂度均为 O(m+n),空间复杂度 O(1)。重点在于比较节点地址而非值,并处理空链表边界情况。

咸鱼开飞机发布于 2026/3/24更新于 2026/5/213K 浏览
相交链表题解与详细分析

题目描述

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

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

A: a1 → a2 ↘ c1 → c2 → c3 ↗
B: b1 → b2 → b3

注意:

  • 题目数据保证整个链式结构中不存在环
  • 函数返回结果后,链表必须保持其原始结构

解题思路

这道题要求找到两个链表的相交节点。由于链表可能长度不同,但相交后的部分长度相同,我们可以通过以下方法解决:

核心思想
  1. 计算链表长度:分别遍历两个链表,得到它们的长度
  2. 对齐起点:让长链表先移动长度差值的步数,使两个链表的剩余长度相等
  3. 同时遍历:两个指针同时移动,比较节点是否相同
为什么这样有效?
  • 如果两个链表相交,那么从相交点到链表末尾的长度是相同的
  • 通过让长链表先走差值步,两个指针会同时到达相交点(如果存在)

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *   int val;
 *   struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *cur1 = headA;
    struct ListNode *cur2 = headB;
    int a = 0;
    int b = 0;
    // 计算链表 A 的长度
    while(cur1) {
        a++;
        cur1 = cur1->next;
    }
    // 计算链表 B 的长度
    while(cur2) {
        b++;
        cur2 = cur2->next;
    }
    // 重置指针到链表头部
    cur1 = headA;
    cur2 = headB;
    int c = 0;
    // 让长链表先移动长度差值的步数
    (a > b) {
        c = a - b;
        (c--) {
            cur1 = cur1->next;
        }
    }  {
        c = b - a;
        (c--) {
            cur2 = cur2->next;
        }
    }
    
    (cur1) {
        (cur1 == cur2) {
             cur1;
        }
        cur1 = cur1->next;
        cur2 = cur2->next;
    }
     ;
}
if
while
else
while
// 同时遍历两个链表,寻找相交节点
while
if
return
return
NULL

代码详解

第一部分:计算链表长度
struct ListNode *cur1 = headA;
struct ListNode *cur2 = headB;
int a = 0;
int b = 0;
// 计算链表 A 的长度
while(cur1) {
    a++;
    cur1 = cur1->next;
}
// 计算链表 B 的长度
while(cur2) {
    b++;
    cur2 = cur2->next;
}
  • 使用两个指针分别遍历两个链表
  • 计数器 a 和 b 分别记录链表 A 和链表 B 的长度
第二部分:对齐起点
cur1 = headA;
cur2 = headB;
int c = 0;
if(a > b) {
    c = a - b;
    while(c--) {
        cur1 = cur1->next;
    }
} else {
    c = b - a;
    while(c--) {
        cur2 = cur2->next;
    }
}
  • 重置指针到链表头部
  • 计算长度差值 c
  • 让长链表的指针先移动 c 步,使两个指针后的剩余长度相等
第三部分:寻找相交节点
while(cur1) {
    if(cur1 == cur2) {
        return cur1;
    }
    cur1 = cur1->next;
    cur2 = cur2->next;
}
return NULL;
  • 两个指针同时移动
  • 比较节点地址是否相同(注意:是比较节点本身,不是节点值)
  • 找到相同节点则返回,否则返回 NULL

执行过程可视化

以题目示例为例:

链表 A: a1 → a2 → c1 → c2 → c3
链表 B: b1 → b2 → b3 → c1 → c2 → c3

执行步骤:

  1. 计算长度:
    • 链表 A 长度:5
    • 链表 B 长度:6
  2. 对齐起点:
    • 长度差:1
    • 链表 B 指针先移动 1 步:b2 → b3 → c1 → c2 → c3
  3. 同时遍历:
    • A: a1 → a2 → c1 → c2 → c3
    • B: b2 → b3 → c1 → c2 → c3
    • 在节点 c1 处相遇,返回 c1

优化方案:双指针法

还有一种更巧妙的方法,不需要计算链表长度:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if (headA == NULL || headB == NULL) return NULL;
    struct ListNode *pA = headA;
    struct ListNode *pB = headB;
    while (pA != pB) {
        pA = pA == NULL ? headB : pA->next;
        pB = pB == NULL ? headA : pB->next;
    }
    return pA;
}

原理:

  • 两个指针分别遍历两个链表
  • 当指针到达链表末尾时,切换到另一个链表的头部
  • 如果两个链表相交,指针会在相交点相遇
  • 如果不相交,指针会同时到达 NULL

复杂度分析

长度差法
  • 时间复杂度:O(m+n),其中 m 和 n 分别是两个链表的长度
  • 空间复杂度:O(1),只使用常数级别的额外空间
双指针法
  • 时间复杂度:O(m+n)
  • 空间复杂度:O(1)

关键点总结

  1. 比较节点地址:注意是比较节点本身(指针地址),不是节点值
  2. 链表无环:题目保证链表无环,简化了问题
  3. 保持原始结构:算法不应该修改链表结构
  4. 边界情况:处理空链表的情况

测试用例考虑

  1. 不相交的链表:返回 NULL
  2. 完全相同的链表:返回头节点
  3. 一个链表是另一个的子集:返回较长链表的头部
  4. 在中间节点相交:返回相交节点
  5. 空链表:返回 NULL

应用场景

这种链表相交问题在实际开发中有多种应用:

  1. 内存管理:检测两个数据结构是否共享内存区域
  2. 图算法:在树或图中寻找公共节点
  3. 版本控制系统:寻找代码分支的合并点
  4. 数据库查询:优化连接查询的执行计划

总结

寻找相交链表节点是一个经典的链表问题,掌握两种解法都很重要:

  1. 长度差法:思路直观,容易理解和实现
  2. 双指针法:代码简洁,不需要计算长度

关键技巧:

  • 利用相交后部分长度相同的特性
  • 通过对齐起点来简化比较过程
  • 注意指针操作和边界条件处理

这道题考察了对链表结构的理解和双指针技巧的应用,是面试中常见的问题之一。

目录

  1. 题目描述
  2. 解题思路
  3. 核心思想
  4. 为什么这样有效?
  5. 代码实现
  6. 代码详解
  7. 第一部分:计算链表长度
  8. 第二部分:对齐起点
  9. 第三部分:寻找相交节点
  10. 执行过程可视化
  11. 优化方案:双指针法
  12. 复杂度分析
  13. 长度差法
  14. 双指针法
  15. 关键点总结
  16. 测试用例考虑
  17. 应用场景
  18. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 嵌入式 Linux 实战:基于泰山派的 AI 网络摄像头
  • PPT 嵌入 VR 图片与全景图播放:霹雳设计助手实操指南
  • DeepSeek 使用指南与高阶提示词技巧
  • 基于 Spring Boot 与 MySQL 的仓库管理系统设计与实现
  • Stable Diffusion 3.5 FP8 在博物馆展览视觉设计中的应用
  • 基于 Java 和 Spring Boot 的驾校在线学习与考试系统设计
  • Linux 部署 OpenClaw 指南
  • Ubuntu 下 AMD AI MAX 395+ 使用 ROCm 加速部署千问 Qwen 模型
  • OpenClaw Windows 部署:Node.js 22+Git+Kimi+ 飞书
  • AVL 树的平衡艺术:用 C++ 实现自平衡二叉搜索树
  • 前端国际化最佳实践指南
  • 基于 SpringBoot 的 Java 在线拍卖系统设计与实现
  • Neo4j 图数据库使用入门
  • 基于 Web 的作业批阅系统设计与实现
  • lwIP 实战解析:基于 CGI 与 SSI 的嵌入式 WebServer 开发
  • Elasticsearch 核心概念与 Java 客户端实战
  • Claude Code 安装与接入智谱 AI 大模型指南
  • AI 编程工具对比:Cursor、GitHub Copilot 与 Claude Code
  • ACM 模式输入输出处理与数据结构构建模板
  • 如何用MCP AI Copilot提升运维效率300%?真实数据告诉你答案

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online