本文参考

出自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. 如何在win10系统上安装linux子系统

    对于软件开发人员来说,linux基本上是一个绕不过去的槛. 因为工作经常要用到linux,电脑用纯linux还是windows + 虚拟机装linux,我一直纠结. 如果装个纯linux,则一些win ...

  2. 【C# 异常处理】 开端

    异常概述 在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式,读取文件是否存在,网络是 ...

  3. CSC.exe编译器使用

    如何用CSC.exe来编译Visual C#的代码文件 Visual C#是微软公司推出的新一代程序开发语言,Visual C#是微软公司.Net FrameWork框架中的一个重要的组成部分,也是微 ...

  4. Python3中__repr__和__str__区别

    示例: class Test(object): def __init__(self, value='hello, world!'): self.data = value >>> t ...

  5. JZ-036-两个链表的第一个公共结点

    两个链表的第一个公共结点 题目描述 输入两个链表,找出它们的第一个公共结点.(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的) 题目链接: 两个链表的第一个公共 ...

  6. LeetCode-018-四数之和

    四数之和 题目描述:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 targe ...

  7. Web端网站兼容性测试如何进行?来看看浏览器的兼容性测试要点

    软件兼容性测试工作的目标是保证软件按照用户期望的方式进行交互.随着用户对来自各种类型软件之间共享数据能力和充分利用空间同时执行多个程序能力的要求,测试软件之间能否协作变得越来越重要. 平台的兼容性,包 ...

  8. postman-接口测试常用test模块

    一.配置环境变量区分不同运行环境(开发.测试.生产等). 对接口进行测试时,不同环境往往对应不同的域名或IP,在Postman里一个接口域名相同但因为地址不同重复写多次很明显是愚蠢的做法,下面我们可以 ...

  9. 矩池云里查看cuda版本

    可以用下面的命令查看 cat /usr/local/cuda/version.txt 如果想用nvcc来查看可以用下面的命令 nvcc -V 如果环境内没有nvcc可以安装一下,教程是矩池云上如何安装 ...

  10. java中的List接口(ArrayList、Vector、LinkedList)

    一.List接口有三个常用的集合(ArrayList.Vector.LinkedList) ArrayList注意事项 ArrayList底层是用数组来实现数据存储的 底层是 transient Ob ...