zoukankan      html  css  js  c++  java
  • Floyd's cycle-finding algorithm

    Floyd's cycle-finding algorithm

    引用维基百科的定义:Floyd's cycle-finding algorithm is a pointer algorithm that uses only two pointers, which move through the sequence at different speeds. It is also called the "tortoise and the hare algorithm".

    此算法主要应用于链表中,主要是判断链表是否有环以及环的起始位置。

    这两个内容刚好对应于 LeetCode 的两道题,此随笔就以这两道题来讲解一下这个巧妙的算法。下面给出这两道题在 LeetCode 中的链接:

    下面的实例代码都用 JavaScript 实现。

    判断链表是否有环

    此算法的主要思想就是双指针,hare 指针一次两步,tortoise 一次一步,如果链表有环,那么 hare 总会追上 tortoise

    hare 一次三步可以吗,应该是可以的,如果有环,它们总会相遇的。但是可能 hare 就要辛苦些, 绕环跑多几圈。

    /**
     * Definition for singly-linked list.
     * function ListNode(val) {
     *     this.val = val;
     *     this.next = null;
     * }
     */
    
    /**
     * @param {ListNode} head
     * @return {boolean}
     */
    var hasCycle = function(head) {
      if (!head) return false;
        
      let tortoise = head;
      hare = head;
      while (hare && hare.next) {
        hare = hare.next.next;
        tortoise = tortoise.next;
        if (hare === tortoise) return true;
      }
      return false;
    };
    

    链表有环,判断链表环的起始位置

    使用上面的算法,我们可以判断 链表是否有环

    如果有环,haretortoise 总会相遇,假设 tortoise 跑了 k 步,那么 hare 就跑了 2k 步,因为 hare 的速度是 tortoise 的两倍。

    那么环的长度就是 k

    此时我们再假设 相遇点环的起点m,那么链表的起点到环的起点就是 k - m 的长度,相遇点再继续前进 k - m 步也会到环的起点,因为环的长度就是 k 嘛。

    那么我们可以让 tortoise 和 hare,一个重回到链表的起点,一个从当前相遇点开始同步前进,一次一步。那么走了 k - m 步后它们就会相遇。

    // 这里让 tortoise 回到起点
    while (hare != tortoise) {
      hare = hare.next;
      tortoise = tortoise.next;
    }
    return hare;
    

    完整的代码如下:

    /**
     * @param {ListNode} head
     * @return {ListNode}
     */
    var detectCycle = function(head) {
      if (!head) return null;
      let hare = head;
      let tortoise = head;
    
      //找到相遇点
      while (hare && hare.next) {
        hare = hare.next.next;
        tortoise = tortoise.next;
        if (hare === tortoise) break;
      }
    
      // 没有相遇点,也就是没有环,直接返回即可
      // 无环情况下,且结点数为奇数个时,hare指向最后一个结点
      if (hare != tortoise) return null;
    
      //让tortoise指针回到开头,两指针重新同步前进,它们就会在环的起点相遇
      tortoise = head;
      while (tortoise !== hare) {
        hare = hare.next;
        tortoise = tortoise.next;
      }
      return hare;
    };
    

    总结

    Floyd's cycle-finding algorithm 既是 tortoise and the hare algorithm,也是 双指针的快慢指针法

    此算法主要应用在链表的 判断链表是否有环 以及 如果链表有环,找出环的起始位置

  • 相关阅读:
    vue实现图片预览旋转/放大缩小/上下切换等功能
    VMware安装遇到的问题
    webstrom弹出Server's certificate is not trusted 解决方法
    this.setData is not a function;at pages/index/index onLoad function;at api request success callback function TypeError: this.setData is not a function
    小程序结构目录
    第一个微信小程序
    用C#开发ActiveX控件给VB使用
    处理WIN7,winxp下安装vb6,出现config.nt 无法运行16位DOS程序故障的方法
    VISUALSVN: UNABLE TO CONNECT TO A REPOSITORY AT URL 无法连接主机的解决办法
    程序全屏开机运行,不允许操作电脑桌面,适用工控机触摸屏
  • 原文地址:https://www.cnblogs.com/AuKing/p/14037900.html
Copyright © 2011-2022 走看看