这篇会详细介绍有关环的入口节点问题,包括代码和理论证明。

首先来看一下如何判断链表中是否存在环。方法很简单,定义两个快慢指针slow和fast,慢指针每次走一步,快指针每次走两步,如果存在环,则快慢指针一定会在环中某个节点相遇,即slow == fast,即可判定链表中有环存在,否则没有。

代码如下:

class Solution(object):def hasCycle(self, head):""":type head: ListNode:rtype: bool"""if not head:return Falsep = head; q = headwhile q.next and q.next.next:p = p.nextq = q.next.nextif p == q:return Truereturn False

证明:用归纳法,假设慢指针刚进入环时,快指针刚好在慢指针后面一个位置,这样下一次慢指针走一步,快指针走两步,二者指向相同节点;假设慢指针刚进入环时,快指针刚好在慢指针后面两个位置,这样经过两步,二者也会指向相同节点,归纳可得,假如存在环,两个指针必定相遇。

再来看一下如何找出环的入口节点。具体做法是当快慢指针相遇时,慢指针不动,另取一指针p指向链表头结点,然后节点p和节点slow同时移动,每次移动一步,二者相遇时指向的节点即为环的入口节点。

代码如下:

class Solution(object):def detectCycle(self, head):""":type head: ListNode:rtype: ListNode"""if not head:returns = f = headwhile f.next and f.next.next:s = s.nextf = f.next.nextif s == f:p = headwhile p != s:p = p.nexts = s.nextreturn preturn

图片来自:https://blog.csdn.net/l294265421/article/details/50478818

证明:这个问题我们借助上图来更好的解释。要证明这个问题,我们首先要证明当两个指针在环中相遇时,慢指针还没有绕环一圈。假设慢指针刚进入环时,快指针还有m步追上慢指针,m一定小于环长度R,由上面的证明可知慢指针再走m步快慢指针即可相遇,而m < R,所以慢指针还没有绕环一圈。

接下来证明,当快慢指针相遇后,慢指针再走LenA步就刚好到达环的入口节点。假设第一次相遇点为Pos,环起点为Join,头结点到环起点的长度为LenA,环起点到第一次相遇点的长度为x,第一次相遇点到环起点的长度为y,环长为R,于是有以下结果:

第一次相遇,slow指针走过的路程:S = LenA + x

第一次相遇,fast指针走过的路程:2S = LenA + n * R + x (相遇时,快指针可能已经绕环好几圈了;至少一圈,n大于等于1,因为快指针先进入环,要追上后进入的慢指针,必须得回到环起点在起点之后才能追上)

由上面两个式子可以得到:LenA = n * R - x

我们的目标是根据上面的式子推导出慢指针在走了S + LenA后刚好到达join点(这是清晰说明这个问题的关键)。

S + LenA = S + n * R - x = S +(n - 1)* R + R - x = S +(n - 1)* R + y,(n - 1)* R表示绕环n - 1圈,S +(n - 1)* R表示停在Pos点,再加上y恰好到达环入口节点,结论得证。

参考:

https://blog.csdn.net/l294265421/article/details/50478818

这里还有一个更具普遍性的证明,比较偏数学证明,有兴趣的可以参考。

https://blog.csdn.net/xgjonathan/article/details/18034825

fatal error lnk1561: 必须定义入口点_链表中是否有环以及找环的入口问题总结相关推荐

  1. fatal error LNK1561: 必须定义入口点问题的我是这样解决的

    2019独角兽企业重金招聘Python工程师标准>>> 接器->高级->入口点改为WinMainCRTStartup 转载于:https://my.oschina.net ...

  2. c语言错误必须定义入口点,MFC项目中:报错:“fatal error LNK1561: 必须定义入口点”解决方法...

    java程序员从笨鸟到菜鸟之(七)一-java数据库操作 本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 数据库访问几乎每一个稍微成型的程 ...

  3. VS2013 编译错误类型: 必须定义入口点

    VS2013 编译错误类型: 必须定义入口点 LINK : fatal error LNK1561: 必须定义入口点 在进行vs2013编译的时候遇到报错1561:必须定义入口点,错误原因大致有以下原 ...

  4. VC++ 常见调试错误:fatal error LNK1561: entry point must be defined

    今天在对软件调试时,碰到一个连接错误"fatal error LNK1561: entry point must be defined",查了很多资料都没能够解决,最终查到是连接命 ...

  5. kernel32.dll已加载但找不到入口点_关键词分析法和工具,关键词分析包括哪几个方面(已帮助1376人)...

    内容导读关键词分析是极其重要的环节,如果关键词分析做好了,优化工作就能事半功倍.大家在做关键词分析的时候,可以参考本文提到的这些方面,应该能够得到很多有用的启示和指导. 做网站优化或者是百度竞价等,分 ...

  6. dllregisterserver找不到入口点_厨房间漏水找不到漏水点,厨房上面漏水 | 影楼

    原文标题:厨房间漏水找不到漏水点,厨房上面漏水 如今人种花,大部分都习惯性自身抽时间时常地去销售市场上看一下,逛一逛,掌握有什么植物,或是该怎么种植.一样的,店家们也依据大家的要求,创造发明出了相对的 ...

  7. java字符串构造函数的应用_构造函数中的参数0需要找不到类型为'java.lang.String'的bean...

    我正在使用Spring Boot 2.X应用程序进行Spring Batch,实际上我已经从git中检出了它的现有代码.在运行该应用程序时,由于以下错误而导致失败仅对我自己,而相同的代码对其他人也有效 ...

  8. 剑指offer_第14题_链表中倒数第k个结点_Python

    题目描述 输入一个链表,输出该链表中倒数第k个结点. 理解 链表详解 python数据结构之链表 解题思路 思路1 确定链表种结点个数lenth 倒数第k个结点就是第length-k+1个结点 需要考 ...

  9. go map fatal error:concurrent map read and map write

    go map fatal error:concurrent map read and map write golang中map并发读写问题及解决方法 go语言切片slice的线程协程安全问题 一.ma ...

最新文章

  1. 把Redis当作队列来用,真的合适吗?
  2. 鸿海拟收购韩国家电企业东洋美吉 价格或达4.5亿美元
  3. [Usaco2008 Feb]Eating Together麻烦的聚餐
  4. 在一个字符串中找到第一个只出现一次的字符
  5. 力改变物体形状举例_人教版八年级物理下册第七章《力》知识点大全
  6. freebsd 安装教程
  7. 2017.9.5.1.语文
  8. iOS开发 mac证书无法展开
  9. Nginx惊群问题分析及解决
  10. auto_ptr自动资源管理器
  11. 2013年7月9日“新单位工作流水账之一”
  12. 计算机硬件设备论文题目,计算机硬件维护论文题目大全 计算机硬件维护论文题目选什么比较好...
  13. 计算机学科a类排名,哈工大17个学科排名位列A类
  14. 学生成绩管理系统 easyx库(半成品
  15. python——spilt和strip用法
  16. win7请不要关闭计算机 正在安装更新,WIN7旗舰版系统总是提示自动安装更新关闭方法...
  17. ThinkPHP 配置详解
  18. 单工通信、半双工通信和全双工通信之间有什么区别。
  19. 关于Servlet编程(2)
  20. leetcode-377:组合总和 Ⅳ

热门文章

  1. vue - config(index.js)
  2. 新版vue-cli搭建多页应用2
  3. [Java]JDBC操作MySQL数据库
  4. oracle 监听服务自动停止与无法启动问题
  5. 使用JavaMail发送邮件
  6. Cracking the coding interview--Q2.2
  7. 二进制数据格式MessagePack:比JSON更快更轻巧
  8. 在内核中增加对yaffs文件系统的支持
  9. CSS文档流与块级元素和内联元素
  10. elasticsearch的父子_elasticsearch父子关系(官方)实际使用中的一些建议