弗洛伊德循环查找算法-原理

本文灵感来自哔哩哔哩视频 

视频链接:

弗洛伊德循环查找算法

算法代码(java)

package rain;class ListNode {int value;ListNode next;public ListNode(int value) {this.value = value;this.next = null;}@Overridepublic String toString() {return "ListNode{" +"value=" + value +'}';}
}
public class FloydCycleDetectionAlgrithm {public static void main(String[] args) {ListNode node0 = new ListNode(4);ListNode node1 = new ListNode(3);ListNode node2 = new ListNode(7);ListNode node3 = new ListNode(8);ListNode node4 = new ListNode(6);ListNode node5 = new ListNode(9);ListNode node6 = new ListNode(2);ListNode node7 = new ListNode(1);ListNode node8 = new ListNode(5);ListNode node9 = new ListNode(2);node0.next = node4;node1.next = node3;node2.next = node7;node3.next = node8;node4.next = node6;node5.next = node9;node6.next = node2;node7.next = node1;node8.next = node5;node9.next = node2;ListNode node = Find(node0);System.out.println(node);}public static ListNode Find(ListNode head) {ListNode slow  = head;ListNode fast = head;while (true) {slow = slow.next;fast = fast.next.next;//第一次相遇//if slow and fast meet, then break the loopif (fast == slow) {break;}}//第二次相遇slow = head;while (true) {slow = slow.next;fast = fast.next;if (fast == slow) {return fast;}}}
}

弗洛伊德循环查找算法中第二次相遇的地方就是循环的起始点,这个性质的证明是基于数学的原理。这是因为在第一次相遇时,慢指针 `slow` 和快指针 `fast` 已经处于同一个循环内。设链表起点到环的起始点的距离为 X,环的起始点到第一次相遇点的距离为 Y,第一次相遇点到环的起始点的距离为Z。

第一次相遇

 ListNode slow  = head;ListNode fast = head;while (true) {slow = slow.next;fast = fast.next.next;//第一次相遇//if slow and fast meet, then break the loopif (fast == slow) {break;}}

设循环长度

1. 在第一次相遇时,慢指针 `slow` 走的距离,

C2是常数

而快指针 `fast` 走 的距离

2. 由于快指针的速度是慢指针的两倍,所以快指针走的距离是慢指针的两倍。因此,有

3. 进一步简化上述等式,得到

这意味着

循环前的距离X = 一定数量循环次数 减去 汇合点前距离Y

4.因为

可得

C3乘以 循环长度长度l 意味着固定的循环量!

找到节点只需要让两个节点分别走X和C3l+Z的路程

此时, 我们可以把slow放在起始位置 每次走一格, 

同时 让fast也是每次走一格

直到相遇 fast == slow 说明相遇的节点就是循环开始的节点

//第二次相遇slow = head;while (true) {slow = slow.next;fast = fast.next;if (fast == slow) {return fast;}}

也就是说,如果此时将慢指针重新指向链表起始点,慢指针再次移动 X 的距离,而快指针从第一次相遇点开始移动 C3l+Z 的距离,它们将会在环的起始点再次相遇。

因此,第二次相遇的地方就是循环的起始点。这个性质是弗洛伊德循环查找算法的关键之一,也是该算法能够正确找到环的起始点的原因。

文末推荐我常用的一个学习网站 可视化运行程序

比如这段链表就可以直观展示出来

网站链接

可视化运行网站

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/413975.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux|操作系统|centos7物理机安装网卡驱动8188gu(内核升级,firmware固件,USB设备管理,module管理)

前言: 目前服务器领域centos7基本是主流的操作系统,而linux相对于Windows来说,软硬件方面的支持是差很多的,在硬件方面来说,以一个免驱的网卡为例,window xp可能不会自动识别到,但Windows10基本…

SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用

SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门 四、Database MetaData 与 S…

Vue3使用

1、列表实现 <el-table :data"tableData" border style"width: 100%" selection-change"handleSelectionChange" :header-cell-style"{text-align:center}"><el-table-column type"selection" width"55"…

Debian系统写Mysql时中文出现乱码无法定入的问题解决方案

原因是操作系统可能精简安装&#xff0c;没有GBK字符集&#xff0c;只有UTF8在转换或使用的时候有问题。 使用locale -a查看系统支持的字符集。正常的比较全的字符集的操作系统如下&#xff1a; 有问题的操作系统字符集如下&#xff1a; 解决方案&#xff1a; 步骤1&#…

shell编程-3

文章目录 shell学习第三天while 循环第一天的小游戏练习: 编写抽同学回答问题的脚本要想让这个脚本永久有效如何知道两个文件里的内存一样&#xff1f;如何判断某个人已经抽过了 文本处理相关命令seqxargsuniqsorttrcutawkpastesplitcoljoin小结一下作业 小知识点写脚本的流程怎…

vue列表飞入效果

效果 实现代码 <template><div><button click"add">添加</button><TransitionGroup name"list" tag"ul"><div class"list-item" v-for"item in items" :key"item.id">{{ i…

使用localstorage清除指定的存储字段

前言&#xff1a;这一操作的来由是关闭页面想清除存储在本地的缓存&#xff0c;但又只想清除指定字段 这里的localStorage 中的数据是持久化存储的&#xff0c;即使浏览器关闭也不会丢失&#xff0c;除非主动删除或者进行清理操作。它跟会话级别还是有差异的。 清除localStora…

Vue中的日历组件 Calendar 实现 考勤打卡记录

日历组件 Calendar 可以自定义在页面添加内容。 实现效果图 1.由于Calendar没有右上角月份切换的API事件&#xff0c;可以给组件源码添加自定义添加一个事件 2.也可以通过自带的input事件来获取日历 3.vue页面完整代码 注释&#xff1a;this.$m(this.beginTime).format(…

【Docker】安装 Nacos容器并根据Nginx实现负载均衡

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Docker实战》。&#x1f3af;&#x1f3af; &…

Zookeeper简介

系列文章目录 Zookeeper安装教程 目录 一、Zookeeper简介 二、Zookeeper的数据结构 三、CPA理论 四、BASE 理论 五、ZooKeeper的特性 前言 这是我的学习笔记&#xff0c;以便后面翻阅。 一、Zookeeper简介 ZooKeeper是一个分布式的、开放源码的分布式应用程序协调服务&a…

JavaScript 入门手册

准备好快速学习 JavaScript了吗&#xff1f; 如果是&#xff0c;那么你需要这份 JavaScript 小抄。它以清晰、简洁和初学者友好的方式介绍了 JavaScript 的基础知识。 将它作为提高 JavaScript 技能的参考或指南。 让我们深入学习。 什么是 JavaScript&#xff1f; JavaSc…

Debian 11.8.0 安装图解

引导和开始安装 这里直接回车确认即可&#xff0c;选择图形化安装方式。 选择语言 这里要区分一下&#xff0c;当前选中的语言作为安装过程中安装器所使用的语言&#xff0c;这里我们选择中文简体。不过细心的同学可能发现&#xff0c;当你选择安装器语言之后&#xff0c;后续安…