• 浅谈双指针技巧(二)---通过双指针判断链表成环问题


    在上一篇文章(https://www.cnblogs.com/jilodream/p/16666435.html)中,我们已经知道可以通过快慢指针,最终判断一个单向链表是否成环。
    一般在判断存在环之后,还有一个经典的问题:
    查找环的起点节点是哪里呢
    力扣 142. 环形链表 II (https://leetcode.cn/problems/linked-list-cycle-ii/)
    也就是查找到下图中的这个位置

    乍一看这个问题很难处理,除非像前文说的通过缓存来判断首次加入到缓存中的节点外,并没有什么其他好的办法。

    如果直觉不能给我答案,我们往往采用数学的办法:

     


    如上图,假设判断有环后,慢指针执行的距离是N,则快指针的执行的距离是2N。他们相遇的点是meet点。我们可以理解2N-N,也就是快指针超过慢指针的距离,其实就是围绕meet节点绕了x圈(x>=0)。
    所以最终的结论就是:(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )

    N=慢指针走的距离=快指针超过慢指针的距离=围绕meet节点走x圈

    此时我们让两个指针(a、b)同时走上述的两个N,也就是一个从head节点,一个从meet节点开始,同速,一直走N步,最终会同时到达meet节点。
    而这个过程的最后一部分,也就是start节点到meet节点,两者的路径其实是重合的。因此这两个指针(a、b)会首先在start节点相遇,然后同时走相同的一段路径,并最终一同走到meet节点。
    如下图:

    a指针移动距离=b指针移动距离=N-lastLen(lastLen表示从start节点到meet节点之间的最短距离+x*环的周长)

    也就是:
    a指针移动距离=b指针移动距离
    所以我们在寻找环的起点start节点时,分为两部分:
    1、通过快慢指针找到二者的相遇点meet节点。(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )
    2、新定义两个节点a、b,分别指向meet 节点和head节点。两者按照相同的速度前进,第一次相遇的节点就是环的起始节点start

    我们直接看代码:

     

    复制代码
     1     public ListNode detectCycle(ListNode head) {
     2         ListNode tempHead = head;
     3         if (tempHead == null) {
     4             return null;
     5         }
     6         ListNode low = tempHead;
     7         ListNode fast = tempHead;
     8         while (true) {
     9             if (fast.next == null || fast.next.next == null) {
    10                 return null;
    11             }
    12             fast = fast.next.next;
    13             low = low.next;
    14             if (fast == low) {
    15                 break;
    16             }
    17         }
    18         ListNode a = tempHead;
    19         ListNode b = fast;
    20         while (true) {
    21             if (a == b) {
    22                 break;
    23             }
    24             a = a.next;
    25             b = b.next;
    26         }
    27         return a;
    28     }
    复制代码

     

  • 相关阅读:
    古代汉语 郭锡良版本 复习要点
    【教3妹学算法-每日1题】采集果实
    释放搜索潜力:基于ES(ElasticSearch)打造高效的语义搜索系统,让信息尽在掌握[2.项目讲解篇],支持Linux/Windows部署安装
    Conda常用命令及Pycharm使用虚拟环境
    神经网络分类任务
    【C语言进阶】动态内存管理
    【Linux】VM及WindowsServer安装
    SpringCloud微服务实战——搭建企业级开发框架(四十八):【移动开发】整合uni-app搭建移动端快速开发框架-使用第三方UI框架
    自定义Systemui(顶部,左侧和底部)
    Zookeeper:实现“命名服务”的 Demo
  • 原文地址:https://www.cnblogs.com/jilodream/p/16670548.html