算法——Floyd判圈算法

介绍

Floyd判圈算法用于判断一个链表中是否有环

思想

使用快慢指针fast, slow,快指针每次走两步fast = fast.next.next,慢指针每次走一步slow = slow.next。当出现fast == null || fast.next == null时,说明链表不存在环,如果存在环,则快指针永远不可能指向null;当出现fast == slow时,说明链表存在环,此时让慢指针回到原点,然后让两个指针的速度相同,每次都只走一步fast = fast.next; slow = slow.next;它们再次相遇的点就是环的入口

论证

图1

对于上面的这张图,不妨设两个指针在点R处第一次相遇,此时让慢指针回到链表头部点P处,让快慢指针同速,每次只走一步,直到第二次相遇。注意,指针在环上是逆时针走的。

第一次相遇时,有 2 t = s f a s t = ∣ P Q ∣ + m C + Q R ⌢ 2t = s_{fast} = |PQ| + mC + \overset{\LARGE{\frown}}{QR} 2t=sfast=PQ+mC+QR t = s s l o w = ∣ P Q ∣ + n C + Q R ⌢ t = s_{slow} = |PQ| + nC + \overset{\LARGE{\frown}}{QR} t=sslow=PQ+nC+QR 其中 s f a s t s_{fast} sfast是第一次相遇前快指针走的距离, s s l o w s_{slow} sslow是第一次相遇前慢指针走的距离, ∣ P Q ∣ |PQ| PQ是点 P P P和点 Q Q Q之间的距离(也就是链表的起点到环的入口的长度), m m m是第一次相遇前快指针绕环转的圈数, n n n是第一次相遇前慢指针绕环转的圈数, C C C是环的周长, Q R ⌢ \overset{\LARGE{\frown}}{QR} QR是从点 Q Q Q沿环逆时针到点 R R R的距离, t t t是移动的次数(快指针每次走两步,慢指针每次走一步)。

用第一个式子减去第二个式子,得 t = ( m − n ) C t = (m - n)C t=(mn)C 再将第三个式子带入第二个式子可得 ∣ P Q ∣ + Q R ⌢ = ( m − 2 c ) C |PQ| + \overset{\LARGE{\frown}}{QR} = (m - 2c)C PQ+QR=(m2c)C 也就是说 ∣ P Q ∣ |PQ| PQ Q R ⌢ \overset{\LARGE{\frown}}{QR} QR的和为环的周长的整数倍,从而可知 ∣ P Q ∣ |PQ| PQ就是从点 R R R沿环逆时针到点 Q Q Q的距离 R Q ⌢ \overset{\LARGE{\frown}}{RQ} RQ,即有 ∣ P Q ∣ = R Q ⌢ |PQ| = \overset{\LARGE{\frown}}{RQ} PQ=RQ

现在考虑第一次相遇与第二次相遇之间的事情,慢指针从链表头部(点 P P P)开始遍历,快指针从第一次相遇的点(点 R R R)开始遍历,慢指针的路程是 ∣ P Q ∣ |PQ| PQ,快指针的路程是 R Q ⌢ \overset{\LARGE{\frown}}{RQ} RQ,由上面的证明 ∣ P Q ∣ = R Q ⌢ |PQ| = \overset{\LARGE{\frown}}{RQ} PQ=RQ可知:它们的第二次相遇点就是环的入口 Q Q Q

从而当两个指针第二次相遇时,它们指向的点就是环的入口得证。

代码

对链表节点的定义如下:

class ListNode {int val;ListNode next;ListNode(int x) {val = x;next = null;}
}

判断链表是否有环的代码如下:

public class Solution {public boolean hasCycle(ListNode head) {ListNode slow = head;ListNode fast = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (slow == fast) {return true;}}return false;}
}

求环的入口的代码如下:

class Solution {public ListNode detectCycle(ListNode head) {ListNode slow = head;ListNode fast = head;while (fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if (slow == fast) {slow = head;while (slow != fast) {slow = slow.next;fast = fast.next;}return slow;}}return null;}
}

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

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

相关文章

1.2-自然语言的分布式表示-基于计数的方法

本篇笔记对应的视频链接为: 3-基于计数的方法表示单词-将文字转换成编号的预处理工作_哔哩哔哩_bilibili;4-基于计数的方法表示单词-使用共现矩阵进行单词的分布式表示_哔哩哔哩_bilibili;5-基于计数的方法表示单词-单词之间相似度计算_哔哩哔…

计算机网络 —— 网络层(CIDR)

计算机网络 —— 网络层(CIDR) CIDR的提出背景什么是CIDR基本概念划分示例应用优势 举个例子路由聚合常用数字 我们今天来看IPv4地址划分的另一种方法 —— CIDR。 CIDR的提出背景 CIDR(无类域间路由,Classless Inter-Domain Ro…

大众汽车裁员加速,38万元遣散费起步

导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 几周前,大众汽车宣布了一项新的裁员计划。 一、裁员行动与额外福利并行 大众汽车近期在裁员行动上取得了显著进展,其遣散…

深度解析:AI Prompt 提示词工程的兴起、争议与未来发展

PART1: 提示词工程的兴起 在人工智能领域中,一个新的领域——提示词工程(prompt engineering)——开始显露头角。 这个领域的核心在于精心设计输入,以引导AI模型产生特定的、期望的输出。 随着AI技术的飞速发展,特别…

Spark MLlib 机器学习

Spark MLlib是一个在Apache Spark上构建的机器学习库,用于解决大规模数据集上的机器学习问题。它提供了一组丰富的机器学习算法和工具,可以用于分类、回归、聚类、推荐和协同过滤等任务。同时,它还提供了一些特征提取、特征转换和特征选择的工…

无头+单向+非循环链表的实现

这里写目录标题 1. 链表1.1 链表的概念及结构1.2 链表的分类 2. 接口实现3. 链表的实现3.1 打印链表3.2 头插3.3 尾插3.4 头删3.5 尾删3.6 单链表查找3.7 在pos之前插入3.8 在pos之后插入3.9 删除pos位置的值3.10 删除pos位置之后的值3.11 链表的释放3.12 动态申请一个节点 4. …

《精通ChatGPT:从入门到大师的Prompt指南》第11章:Prompt与AI的未来

第11章:Prompt与AI的未来 11.1 技术发展的新方向 在迅速发展的人工智能领域,Prompt工程作为与AI模型交互的核心方式,正处于技术创新的前沿。未来几年,Prompt工程将沿着多个新方向发展,这些方向不仅会改变我们与AI互动…

Golang 高级面试题

在准备 Golang 高级面试时,通常会涉及到多种关键领域。本文将涵盖各个领域的具体问题示例和实现代码。 数据结构与算法 实现堆、链表、栈、队列、哈希表 1.最小堆: 最小堆是一种完全二叉树,树中每个节点的值都小于等于其子节点的值。常用于实现优先队列。 package main…

Spring AI 第三讲Embeddings(嵌入式) Model API 第一讲OpenAI 嵌入

Spring AI 支持 OpenAI 的文本嵌入模型。OpenAI 的文本嵌入测量文本字符串的相关性。嵌入是一个浮点数向量(列表)。两个向量之间的距离可以衡量它们之间的相关性。距离小表示关联度高,距离大表示关联度低。 先决条件 您需要与 OpenAI 创建一…

Python怎么降雪:一场编程的奇幻之旅

Python怎么降雪:一场编程的奇幻之旅 在编程的世界里,我们通常与数字、逻辑和算法打交道,但今天,让我们打破常规,走进一个更加奇幻的领域——使用Python来模拟降雪的场景。这不仅是一场编程的挑战,更是一次…

idm究竟有哪些优势

IDM,即Internet Download Manager,是一款功能强大的下载管理软件,具有许多优势。以下是IDM的主要优势: 加快下载速度:IDM采用多线程技术下载文件,能够同时分割文件并使用多个连接下载,从而大大提…

【Linux】rsync远程数据同步工具使用

一、rsync工具介绍 rsync是一个用于在本地或远程系统之间同步文件和目录的工具。它通过比较源和目标文件的元数据(例如修改时间和大小)来确定需要同步的内容,然后仅传输必要的数据进行更新,从而实现高效的同步操作。 rsync有如下特…

Transformer学习之SwinTransformer

1.算法简介 本文主要参考自以下链接,整理成线上的形式用于备忘,排版太麻烦了直接贴图,参考的朋友慎重,不如直接看参考链接,后期有了新的理解继续更正。 参考链接1:Swin-Transformer网络结构详解_swin tran…

程序员如何转行成为一个漫画自媒体-连载2

仿写关于如何撰写文案的内容如下: 如何编写文案? 从零开始自己创作显然效率过低,初期阶段还是需要从其他漫画公众号中学习技巧,然而只能看到最终成品,却无法获得他们的实际文案。 不过,通过广泛的阅读&…

【文件导出2】导出html文件数据

导出html文件数据 文章目录 导出html文件数据前言一、实现代码1.controller层2.接口层3.接口实现类4.FileUtil 工具类 二、文件导出效果总结 前言 springBoot项目实现在线导出html文件数据的功能。 一、实现代码 1.controller层 GetMapping("/record/_export") Ap…

.NET4.8安装失败解决办法

在windows 2008 r2 安装.net 4.8 ,一开始下载 .net 4.8 的web 安装包,链接如下: https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/9b7b8746971ed51a1770ae4293618187/ndp48-web.exe 安装过…

Flutter中同步与异步

一,同步/异步的理解 1,await:同步机制 同步操作会阻止其他操作执行,直到完成为止。同步就好比打电话一样,打电话时都是一个人在说另一个人听,一个人在说的时候另一个人等待,等另一个人说完后再…

【Git】远程操作 -- 详解

一、理解分布式版本控制系统 我们目前所说的所有内容(工作区、暂存区、版本库等等)都是在本地,也就是在我们的笔记本或者计算机上。而我们的 Git 其实是分布式版本控制系统。 上面这段话是什么意思呢? 可以简单理解为&#xff1…

java算法篇之二分查找的公共函数

Arrays.binarySearch 方法的底层实现是使用经过优化的二分查找算法。以下是大致的二分查找算法实现步骤: 首先,确定搜索范围的起始索引 low 和结束索引 high,它们分别初始化为数组的起始位置和结束位置。在每一轮循环中,计算中间…

node-mysql中占位符?的使用

要mysql执行的命令串如果是固定的,那么不需要使用占位符,如果其中的一些参数允许在执行前可自由设定,那么使用占位符就很必要,这样你可以不需要由自己来拼接出一个完整的执行串,只需要在执行串模板上将占位符的参数设置…