本文参考

出自LeetCode上的题库 —— 环形链表II,哈希表和快慢指针两种解法都需要O(n)的时间,但快慢指针仅占用O(1)的空间

https://leetcode-cn.com/problems/linked-list-cycle-ii/

环形链表问题

给定一个链表的头节点 head,返回链表开始入环的第一个节点(不允许修改链表)
如果链表无环,则返回null。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环

示例1:
输入:head = [3,2,0,-4]
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点

示例2:
输入:head = [1,2]
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点

示例3:
输入:head = [1]
输出:返回 null
解释:链表中没有环

解题思路

首先是特殊情况,当没有节点,或有节点却不存在环的情况下,容易通过节点或节点的next指针是否空进行判断

当节点间存在环路时,第一种直观的解法,使用一个指针沿着链路走下去,每走一步将节点存入set集合,当碰到重复出现的节点时,该节点就是环路的入口;

第二种解法需要应用两遍双指针,可能刚接触这道题时已经想到了快慢指针,但是我们无法保证快指针和慢指针相遇的位置一定是环路的入口,以至于否定了这种解法。此处需要一定的数学分析,在快慢指针相遇的位置引入第三个指针:

令总节点数为$n$,头节点为$head$,环路的入口节点为$entry$,环路中快慢指针相遇的节点位置为$meet$,定义距离$a=Distance(head,entry)$,距离$b=Distance(entry,meet)$,距离$c=Distance(meet,entry)$,满足$n=a+b+c$

当快慢指针相遇时,快指针走过的路径长度为$d_{fast}=a+n(b+c)+b$,慢指针走过的路径长度为$d_{slow}=a+b$,我们预先设置快指针每次走两步,慢指针每次走一步,则$d_{fast}=2d_{slow}=a+n(b+c)=2(a+b)$,化简得$a=c+(n-1)(b+c)$,$a$的长度是$c$的长度加上$(n-1)$圈的环路长度

因此,我们引入第三个指针ptr,慢指针从相遇位置开始移动,ptr从头指针开始移动,由公式$a=c+(n-1)(b+c)$可知,二者相遇的位置即为环路的路口

哈希表解法

class ListNode:

  def __init__(self, x):

    self.val = x

    self.next = None

class
Solution:

  def detect_cycle_1(self, head: ListNode) -> ListNode:

    if head is None or head.next is None:

      return None

    node_set = set()

    curr_node = head

    while curr_node not in node_set:

      node_set.add(curr_node)

      if curr_node.next is None:

        return None
      else
:

        curr_node = curr_node.next

    return curr_node

快慢指针解法

def detect_cycle_2(self, head: ListNode) -> ListNode:

  slow = fast = head

  while fast is not None:

    # 慢指针每次走一步 

    slow = slow.next

    if fast.next is None:

      return None

    # 快指针每次走两步 


    fast = fast.next.next

    # 快慢指针相遇 

  if fast == slow:

    ptr = head

    # 建立新的双指针走法 

    while ptr != slow:

      ptr = ptr.next
      slow = slow.next

      return ptr

    return None

打败算法 —— 环形链表 II的更多相关文章

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

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

  2. LeetCode142 环形链表 II

    给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 说明:不允许修改给定的链表. 进阶:你是否可以不用额外空间解决此题? //章节 - 链表 //二.双指针技巧 //2.环 ...

  3. Leetcode 142.环形链表II

    环形链表II 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 说明:不允许修改给定的链表. 进阶:你是否可以不用额外空间解决此题? 链表头是X,环的第一个节点是Y,sl ...

  4. Leetcode.142-Linked-list-cycle-ii(环形链表II)

    环形链表II 思路 https://www.cnblogs.com/springfor/p/3862125.html https://blog.csdn.net/u010292561/article/ ...

  5. LeetCode 142. 环形链表 II(Linked List Cycle II)

    142. 环形链表 II 142. Linked List Cycle II 题目描述 给定一个链表,返回链表开始入环的第一个节点.如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整 ...

  6. Java实现 LeetCode 142 环形链表 II(二)

    142. 环形链表 II 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始 ...

  7. 【LeetCode】142. 环形链表 II

    142. 环形链表 II 知识点:链表:set:快慢指针 题目描述 给定一个链表,判断链表中是否有环. 给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表 ...

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

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

  9. LeetCode 142:环形链表 II Linked List Cycle II

    给定一个链表,返回链表开始入环的第一个节点. 如果链表无环,则返回 null. 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始). 如果 pos 是 - ...

随机推荐

  1. C#中的泛型 / 泛型类 / 数组、ArrayList和List三者的区别

    在C#中数组,ArrayList,List都能够存储一组对象,那么这三者到底有什么样的区别呢. 数组 数组在C#中最早出现的.在内存中是连续存储的,所以它的索引速度非常快,而且赋值与修改元素也很简单. ...

  2. 个人c#编码约定 继承C#编码约定

    1.内插字符 串取代  字符串复合格式设置 使用这个写法: Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it' ...

  3. 举例说明EF CORE中模型之间的一对多、多对多关系的实现

    该例子是我临时想出来的,不具有任何的实际意义.类图如图1所示. 图1 类代码: [Table("student")] public class Student { public i ...

  4. JavaWeb-网络编程

    Java网络编程 推荐阅读: 计算机网络:https://www.cnblogs.com/zwtblog/tag/计算机网络/ 计算机网络基础 利用通信线路和通信设备,将地理位置不同的.功能独立的多台 ...

  5. 【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入

    前言:在C/S架构上,WPF无疑已经是"桌面一霸"了.在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用.但是WPF也有很多年的历史了,并且基于MVVM ...

  6. Java:各版本官方文档

    JDK16:https://docs.oracle.com/en/java/javase/16/docs/api/index-files/index-1.html JDK15:https://docs ...

  7. WPS:公式在中间,编号靠右

    1.新建表格1*3 2.在中间单元格内输入公式,在右边单元格中输入编号 3.在"开始"菜单栏找到"居中"和"靠右"两个按钮,给中间单元格设置 ...

  8. GeoServer-REST应用:基于Qt网络编程一键同步发布空间数据和样式至GeoServer

    @ 目录 简介 配置 步骤   1.引入Qt网络模块   2.创建网络管理.网络响应.网络请求   3.创建工作空间   4.创建数据存储并上传数据   5.上传样式文件   6.图层发布   6.图 ...

  9. php模式的设计

    工厂模式是我们最常用的实例化对象模式,是用工厂方法代替new操作的一种模式. 工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,虽然工厂方法可以任意命名这个静态 ...

  10. 微信小程序获取手机号

    wxml 代码: <!-- 授权 --> <button type="primary" open-type="getUserInfo" bin ...