从十字路口相遇到链表交点:探索相交链表问题

生活中的相遇问题

想象两个人从不同的地方出发,最后在一个十字路口相遇。他们可能走过不同长度的路程,但最终会在同一个点汇合。这就很像我们今天要讨论的相交链表问题:两个链表从不同的起点出发,在某个节点相交,然后共享后续的路径。

问题描述

LeetCode第160题"相交链表"是这样描述的:给你两个单链表的头节点 headA 和 headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null。

例如:

A链表:      a1 → a2

                      c1 → c2 → c3

B链表: b1 → b2 → b3

输出:返回节点c1

最直观的解法:哈希表记录

就像在一个城市里标记每个人走过的地方,最简单的方法是用一个哈希表记录第一个人走过的所有位置,然后看第二个人的路径中是否有重复的地方。

哈希表方法的实现

public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// 使用HashSet记录链表A中的所有节点
Set<ListNode> visited = new HashSet<>(); // 遍历链表A,将节点加入集合
ListNode current = headA;
while (current != null) {
visited.add(current);
current = current.next;
} // 遍历链表B,查找第一个在集合中出现的节点
current = headB;
while (current != null) {
if (visited.contains(current)) {
return current;
}
current = current.next;
} return null;
}
}

优化解法:双指针技巧

仔细思考,我们发现一个有趣的现象:如果两个人分别走对方的路,他们最终一定会相遇!这就是双指针解法的灵感来源。

双指针方法的原理

想象两个人在散步:

  1. A从链表A出发,走完后转到链表B继续走
  2. B从链表B出发,走完后转到链表A继续走
  3. 如果链表相交,他们一定会在相交点相遇
    • 因为他们走过的总路程是相同的:链表A长度 + 链表B长度

示例运行

假设链表A:1→2→3→4,链表B:5→6→3→4(3是相交点)

指针A:1 → 2 → 3 → 4 → 5 → 6 → [3] ← 相遇!
指针B:5 → 6 → 3 → 4 → 1 → 2 → [3] ← 相遇!

Java代码实现

public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
} // 初始化两个指针
ListNode pointerA = headA;
ListNode pointerB = headB; // 当两个指针不相等时继续移动
while (pointerA != pointerB) {
// 移动指针A,如果到达末尾则转到链表B
pointerA = (pointerA == null) ? headB : pointerA.next;
// 移动指针B,如果到达末尾则转到链表A
pointerB = (pointerB == null) ? headA : pointerB.next;
} // 返回相交点(如果不存在相交点,两个指针都会是null)
return pointerA;
}
}

解法比较

让我们比较这两种方法:

哈希表法:

  • 时间复杂度:O(m+n)
  • 空间复杂度:O(m),m为链表A的长度
  • 优点:思路直观,容易理解
  • 缺点:需要额外的空间存储节点

双指针法:

  • 时间复杂度:O(m+n)
  • 空间复杂度:O(1)
  • 优点:不需要额外空间,优雅简洁
  • 缺点:理解起来稍微有点难度

实用技巧总结

解决链表相交问题的关键点:

  1. 理解相交后的节点都是共享的
  2. 考虑特殊情况(如空链表、不相交的情况)
  3. 善用双指针技巧
  4. 利用数学特性(路程相等原理)

相关的链表问题:

  • 判断链表是否有环
  • 找到链表环的入口
  • 链表的中间节点

小结

通过相交链表这道题,我们学会了如何巧妙地使用双指针技巧来解决看似复杂的问题。这种思维方式不仅能解决算法题,在处理数据流、文件比较等实际问题时也很有用。记住,当遇到需要找到两个序列共同元素的问题时,双指针技巧往往能提供一个优雅的解决方案!

延伸思考:

  1. 如果链表可能有环,这个算法还有效吗?
  2. 如果要找到所有的相交节点,应该如何修改算法?
  3. 在分布式系统中,如何处理类似的"路径相交"问题?

作者:忍者算法

公众号:忍者算法

回复【刷题清单】获取更多经典题目解析

回复【加群】加入算法/面试交流群,一起学习进步

‍ 回复【代码】获取GitHub完整题解项目,包含Java/Python/JavaScript/Go/C++多语言实现

【忍者算法】从十字路口相遇到链表交点:探索相交链表问题|LeetCode第160题 相交链表的更多相关文章

  1. 【python】Leetcode每日一题-旋转链表

    [python]Leetcode每日一题-旋转链表 [题目描述] 给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置. 示例1: 输入:head = [1,2,3,4,5] ...

  2. 【python】Leetcode每日一题-反转链表 II

    [python]Leetcode每日一题-反转链表 II [题目描述] 给你单链表的头节点 head 和两个整数 left 和 right ,其中 left <= right .请你反转从位置 ...

  3. [Leetcode] 第148题 排序链表

    一.题目描述 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序. 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示 ...

  4. LeetCode 上最难的链表算法题,没有之一!

    题目来源于 LeetCode 第 23 号问题:合并 K 个排序链表. 该题在 LeetCode 官网上有关于链表的问题中标注为最难的一道题目:难度为 Hard ,通过率在链表 Hard 级别目前最低 ...

  5. c++ LeetCode (网易面试题和链表以及树篇) 五道算法例题代码详解(三)

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11209807.html 一.1道网易c++的面试题 我当时第一时间的解答方案 #include ...

  6. 《数据结构与算法之美》 <05>链表(下):如何轻松写出正确的链表代码?

    想要写好链表代码并不是容易的事儿,尤其是那些复杂的链表操作,比如链表反转.有序链表合并等,写的时候非常容易出错.从我上百场面试的经验来看,能把“链表反转”这几行代码写对的人不足 10%. 为什么链表代 ...

  7. 【算法训练营day4】LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表II

    [算法训练营day4]LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表 ...

  8. 【LeetCode题解】141_环形链表

    目录 141_环形链表 描述 解法一:哈希表 思路 Java 实现 Python 实现 解法二:双指针(龟兔算法) 思路 Java 实现 Python 实现 141_环形链表 描述 给定一个链表,判断 ...

  9. 代码随想录第四天| 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点 、160.链表相交、142.环形链表II

    今天链表致死量 第一题 public static class ListNode { int val; ListNode next; ListNode() {} ListNode(int val) { ...

  10. 【LeetCode题解】142_环形链表2(Linked-List-Cycle-II)

    目录 描述 解法一:哈希表 思路 Java 实现 Python 实现 复杂度分析 解法二:双指针 思路 Java 实现 Python 实现 复杂度分析 描述 给定一个链表,返回链表开始入环的第一个节点 ...

随机推荐

  1. 反微服务架构(A Macro Services Framework)

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 反微服务架构(A Macro Services Frame ...

  2. Nginx https证书生成

    一.证书和私钥的生成 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 1.创建服务器证书密钥文件 server.key: ...

  3. Qt/C++音视频开发66-音频变速不变调/重采样/提高音量/变速变调/倍速播放/sonic库使用

    一.前言 之前在做倍速这个功能的时候,发现快速播放会有滴滴滴的破音出现,正常1倍速没有这个问题,尽管这个破音间隔很短,要放大音量才能听到,但是总归是不完美的,后面发现,通过修改qaudiooutput ...

  4. Qt编写地图综合应用31-仪表盘

    一.前言 用Qt开发仪表盘控件非常方便,无论是用widget的painter还是qml,尤其是qml,内置的那些动画效果非常适合做这类的应用,这次不讨论如何用qt开发仪表盘,而是直接用echart内置 ...

  5. Qt编写安防视频监控系统23-图片地图

    一.前言 图片地图这个模块是后面新增加进去的,主要是安防领域还有很多应用场景是一个区域比如就一个学校,提供一个学校的平面图或者鸟瞰图,然后在该地图上放置对应的摄像机,双击该摄像机图标可以查看对应的实时 ...

  6. Web网页端IM产品RainbowChat-Web的v7.0版已发布

    一.关于RainbowChat-Web RainbowChat-Web是一套Web网页端IM系统,是RainbowChat的姊妹系统(RainbowChat是一套基于开源IM聊天框架 MobileIM ...

  7. IM开发干货分享:网易云信IM客户端的聊天消息全文检索技术实践

    1.引言 在IM客户端的使用场景中,基于本地数据的全文检索功能扮演着重要的角色,最常用的比如:查找聊天记录.联系人,就像下图这样. ▲ 微信的聊天记录查找功能 类似于IM中的聊天记录查找.联系人搜索这 ...

  8. spark (六) RDD算子(operator)

    目录 1 转换算子(transformer)(将旧的RDD包装成新RDD) 1.1 单值类型 1.1.1 map 1.1.2 mapPartition 1.1.3 mapPartitionsWithI ...

  9. [开源项目]YOLOv8_Efficient

    Yolov8_Efficient Simple and efficient use for yolov8 About This is an unofficial repository maintain ...

  10. 单点认证(SSO)方案调研总结

    SSO方案 SSO介绍 单点登录(SSO)是一种身份验证解决方案,可让用户通过一次性用户身份验证登录多个应用程序和网站.这意味着用户只需输入一次用户名和密码,即可访问所有相互信任的系统,而无需在每个系 ...