首页 > 编程语言 >【数据结构与算法】之龟兔赛跑算法

【数据结构与算法】之龟兔赛跑算法

时间:2024-10-23 20:16:22浏览次数:7  
标签:head ListNode pos next 链表 算法 数据结构 之龟 节点

目录

一、龟兔赛跑算法

1.1 阶段1

1.2 阶段2

1.3 为什么呢?

二、判断是否有环

2.1 问题描述

2.2 示例

2.3 代码实现

三、找到环入口

3.1 问题描述

3.2 示例

3.3 代码实现

总结


本文主要介绍以环形链表相关的算法,主要采用Java语言实现,这类算法又称Floyd's Tortoise and Hare Algorithm (Floyd 龟兔赛跑算法),不得不说,这个原理挺神奇的就解决了,环形链表的问题。

注意:以下代码有关链表的算法实现均基于以下链表节点类:

//链表节点类
public class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

龟兔算法动画来自:

Floyd's Hare and Tortoise Algorithm Demo - One Step! Code 

相关教程:

一、龟兔赛跑算法

如果链表上存在环,那么在环上以不同速度前进的两个指针必定会在某个时刻相遇(如上图所示)。算法分为两个阶段。

1.1 阶段1

  • 龟一次走一步,兔子一次走两步

  • 当兔子能走到终点时,不存在环

  • 当兔子能追上龟时,可以判断存在环

存在环情况:(上帝视角)

不存在环情况:(上帝视角)

1.2 阶段2

  • 从它们第一次相遇开始,龟回到起点,兔子保持原位不变

  • 龟和兔子一次都走一步

  • 当再次相遇时,地点就是环的入口

a.第一次相遇:(证明已经是环)

b.龟回到起点,兔子保持原位不变:

c.再次相遇:再次相遇的位置为环入口

!!!!!!

1.3 为什么呢?

********精髓之处********

  • 设起点到入口走 a 步(本例是 7),绕环一圈长度为 b(本例是 5),

  • 那么从起点开始,走 a + 绕环 n 圈,都能找到环入口

  • 第一次相遇时

    • 兔走了 a + 绕环 n 圈(本例 2 圈) + k,k 是它们相遇距环入口位置(本例 3,不重要)

    • 龟走了 a + 绕环 n 圈(本例 0 圈) + k,当然它绕的圈数比兔少

    • 兔走的距离是龟的两倍,所以龟走的 = 兔走的 - 龟走的 = 绕环 n 圈

  • 而前面分析过,如果走 a + 绕环 n 圈,都能找到环入口,因此从相遇点开始,再走 a 步,就是环入口

  • 实在不理解的话,可以理解为快慢指针,遵循以上结论

知晓了龟兔算法的精髓后,下来解决这两个经典问题!

二、判断是否有环

2.1 问题描述

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false

2.2 示例

示例一:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例二:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例三:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

2.3 代码实现

public boolean hasCycle(ListNode head) {
    ListNode h = head; // 兔
    ListNode t = head; // 龟
    while (h != null && h.next != null) {
        t = t.next;
        h = h.next.next;
        if(h == t){  // 龟兔相遇时,证明是环
            return true;
        }
    }
    return false;
}

三、找到环入口

3.1 问题描述

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

3.2 示例

示例一:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

示例二:

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

示例三:

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

3.3 代码实现

public ListNode detectCycle(ListNode head) {
    ListNode t = head; // 龟
    ListNode h = head; // 兔
    while (h != null && h.next != null) {
        t = t.next;
        h = h.next.next;
        if (h == t) {  //证明是环
            t = head;  //龟回到起点
            while (true) {
                if (h == t) { //再次相遇即为环入口
                    return h;
                }
                h = h.next; //同时前进
                t = t.next; //同时前进
            }
        }
    }
    return null;
}

总结

本文主要介绍了链表算法中经典问题:龟兔赛跑算法,主要是判断链表中是否有环,以及如何找到环的入口。最重要的是龟兔赛跑算法的两个阶段和背后的原理。并提供了Java代码实现。希望对各位有所帮助,下期见,谢谢~

标签:head,ListNode,pos,next,链表,算法,数据结构,之龟,节点
From: https://blog.csdn.net/weixin_64178283/article/details/143191777

相关文章

  • 基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
    1.算法运行效果图预览(完整程序运行后无水印)   将FPGA的仿真结果导入到MATLAB中,分别得到MATLAB的结果和FPGA的结果:   2.算法运行软件版本vivado2019.2 matlab2022a 3.部分程序(完整版代码包含详细中文注释和操作步骤视频)`timescale1ns/1ps////C......
  • 【图论】(五)最短路径算法(D / BF / SPFA / F / A*)
    最短路径算法(D/BF/SPFA/F/A*)1.最短路径之dijkstra(D算法)思路模拟过程程序实现拓展2.dijkstra算法堆优化思路程序实现3.Bellman_ford算法(BF算法)松弛模拟过程拓展4.Bellman_ford队列优化算法(又名SPFA)模拟过程拓展5.Bellman_ford之判断负权回路思路拓展6......
  • 磁盘和磁盘调度算法
    磁盘的结构如果内道和外道扇区数量一样,那么磁盘的存储能力受限于内道的最大记录密度。而为了提高磁盘的存储容量,充分利用磁盘外层磁道的存储能力,现代磁盘不再将内外磁道划分为相同数目的扇区,而是将盘面划分为若干换代,同一环带内的所有磁道具有相同的扇区数,显然,外层环带的磁道......
  • 【算法笔记】前缀和算法原理深度剖析(超全详细版)
    【算法笔记】前缀和算法原理深度剖析(超全详细版)......
  • 代码训练营第22天|补第9天的KMP算法,28. 找出字符串中第一个匹配项的下标|459.重复的子
    前置知识文章链接:https://programmercarl.com/0028.实现strStr.html#思路KMP的经典思想就是:当出现字符串不匹配时,可以记录一部分之前已经匹配的文本内容,利用这些信息避免从头再去做匹配。前缀表:next数组就是一个前缀表(prefixtable)。前缀表是用来回退的,它记录了模式串与主......
  • 信息学奥赛复赛复习20-CSP-S2019-01格雷码-数据类型范围、unsigned 关键字、无符号范
    PDF文档回复:202410231P5657[CSP-S2019]格雷码[题目描述]通常,人们习惯将所有n位二进制串按照字典序排列,例如所有2位二进制串按字典序从小到大排列为:00,01,10,11。格雷码(GrayCode)是一种特殊的nn位二进制串排列法,它要求相邻的两个二进制串间恰好有一位不同,特别地......
  • 信息学奥赛复赛复习20-CSP-S2019-01格雷码-数据类型范围、unsigned 关键字、无符号范
    PDF文档公众号回复关键字:202410231P5657[CSP-S2019]格雷码[题目描述]通常,人们习惯将所有n位二进制串按照字典序排列,例如所有2位二进制串按字典序从小到大排列为:00,01,10,11。格雷码(GrayCode)是一种特殊的nn位二进制串排列法,它要求相邻的两个二进制串间恰好有一位不同......
  • [算法题解] Codeforces round 979 --D. QED's Favorite Permutation
    题目链接:https://codeforces.com/contest/2030/problem/D题目:题解:FavotitePermutation即每个数满足i=p[i];此题中,p数组每次询问后保持不变,s根据询问而改变。因此每次需要进行交换的数的位置是相同的,只需要检验s变更后,操作能否满足交换需求与否。故创建需数组need,预处理nee......
  • 二、KNN算法详解
    KNN算法详解前言一、KNN算法思想二、实现步骤2.1收集数据2.2准备数据2.3选择K值2.4计算距离2.5找到最近的邻居2.6决策三、关键要素(细节)3.1K值的选择3.2距离的计算3.2.1欧氏距离3.2.2曼哈顿距离3.2.3切比雪夫距离3.2.4闵氏距离3.3决策规则四、API介绍4.......
  • AI智能分析视频分析网关算法定制智能分析网关V4安全帽检测/反光衣检测/通用工服检测算
    在现代工业和社会活动中,工作场所的安全越来越受到重视。为了确保员工的安全,许多行业都制定了严格的安全规范,其中包括正确佩戴个人防护装备,如安全帽和反光衣。然而,人工监控这些规范的执行情况往往效率低下,且容易出现疏漏。随着人工智能技术的发展,AI智能分析网关应运而生,它通过先进......