快慢指针-Floyd判圈算法

news2024/11/19 0:23:08

对于环形链表是否存在环的做法,普通算法可以通过额外Hash数组来存储链表元素,直到Hash数组中出现重复元素。时间复杂度O(n),空间复杂度O(n)

Floyd判圈算法通过利用快慢指针的移动来实现,时间复杂度O(n),空间复杂度O(1)

一、环形链表

这个不需要过过多的介绍,环形链表就是存在一个节点被2个节点指向,形成了一个闭环。

需要注意的是,一个节点可以被两个节点指向,但是不可能一个节点指向多个节点,所以不会出现一下情况:

二、算法结论

存在不同速度的快慢指针(slow & fast),慢指针每周期移动1个节点,快指针每周期移动2节点

1、因为快指针比慢指针速度快,所以如果链表中不存在环时,快慢指针永远不得相遇,直到Fast移动到尾部结束,时间复杂度O(n),因为Fast指针速度是Slow指针两倍,所以当Fast指针到达尾部时,Slow指针走了一半,即S指向中间值。

2、如果存在环,Fast先进入到环内,并开始做绕环移动,Slow和Fast在环内经过n次移动后,必然会相遇

3、快慢指针在环内第一次相遇后,将其中一个指针重置到head位,当他们再次相遇后指向的节点为入环节点

三、算法证明

1、每次循环,为什么快慢指针一定要快1步,是否可以前进更多?(Slow前进1格,Fast前进2格)

这是因为快慢指针如果相距更多的步,可能存在环内永远不会相遇的情况,比如慢指针前进1格,快指针前进4格时,如下

因为环节点数据量为3个,所以对于Fast指针来说每次循环等于前进1格,而慢指针也前进1格,所以两者永远不能相遇。

因此想要快慢指针在环内能必然或者更快的相遇,那需要他们每次循环后,距离-1,直到相遇。F指针比S指针快1步,可以更好的保障其在环境一定能够相遇,或者更早的相遇。

2、为什么快慢指针在环内一定会相遇?

假如快慢指针此时都在环内,他们相距距离为N,因为环是无限循环的,假设次数S指针在F指针前,即S-F=N

 因为F指针比S指针快1步,所以进行1次移动后:

S+1-(F+2) = S-F -1 = N-1 ,即执行一次后两者的距离-1,因此在n次循环后,必然会出现相遇。

此时如果将设F指针速度为vf, 慢指针速度为vs,同时要确保一定相遇满足N-1,则:

S+vs -(F +vf) = N-1   

  --> S-F + vs-vf = n-1  

  --> vs - vf = 1,即相差1步

同时N为两者的距离,肯定是小于环的长度的,所以在S指针进环后,第1圈内一定会相遇

结论:

首先F指针每次比S指针快1步,可以确保在环中一定可以相遇,如果快更多,则不能保证或需要更多的循环。

3、入口节点结论证明

上面已经证明了F\S在环中一定是能够相遇的,且S进环后,第一圈一定会相遇,那么假设F\S

在P点相遇

因为F比S快1步,所以F在环内已经跑了1圈了

因此F行驶距离:AC + 2CP + PC

S行驶距离:AC + CP

因为F速度为S的两倍,因此 AC + 2CP + PC = 2(AC + CP)得出 AC = PC

即:在第一次相遇时,PC和AC的长度是一样的,因此此时将任意节点重置到A位,并两者均以相同的速度前进,必然会在C点相遇,因此C点为入口点。

4、原理理解了算法就比较简单了

判断单向链表是否存在环,且返回入环节点

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null){
           return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(true){
           if(fast ==null || fast.next == null){
              return null;
           }
           fast = fast.next.next;
           slow = slow.next;
           if(fast == slow){
               break;
           }
        }
        fast = head;
        while(fast!=slow){
            fast = fast.next;
            slow = slow.next;
        }
        return fast;
    }
}

 总结:

Floryd算法是快慢指针算法一种实现,快慢指针 | 双指针算法思想用法非常广泛,比如上述提到的找到中间位数、删除倒数第N节点等等

附上:双指针算法-删除链表倒数第n个节点

public class DoublePointer {
    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        ListNode hea2 = new ListNode(2);
        ListNode hea3 = new ListNode(3);
        ListNode hea4 = new ListNode(4);
        ListNode hea5 = new ListNode(5);
        head.next = hea2;
        hea2.next=hea3;
        hea3.next=hea4;
        hea4.next=hea5;
        Solution solution = new Solution();
        solution.removeNthFromEnd(head , 2);
    }
}

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if(head == null){
            return null;
        }
        // 建立虚拟头节点,防止出现链表只有1个元素时,无法删除情况
        ListNode listNode = new ListNode(-1);
        listNode.next = head;
        ListNode slow = listNode;
        ListNode fast = listNode;
        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }
        while(true){
            if(fast == null || fast.next == null){
                break;
            }
            fast = fast.next;
            slow = slow.next;
        }
        slow.next = slow.next.next;
        return listNode.next;
    }
}

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

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

相关文章

09 STM32 - PWM

9.1 PWM简介 脉冲宽度调制(Pulse Width Modulation,简称PWM)&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点&#xff0c;就是对脉冲宽度的控制。 9.2 PWM波原理 如下图所示&#xff0c;使用定时器定时&#xff0c;从0开始&#x…

Linux grep命令(grep指令)grep --help各选项介绍(待更)

文章目录 grep --help英文中文 使用示例-E, --extended-regexp&#xff1a;此选项表示模式为扩展正则表达式。-F, --fixed-strings&#xff1a;此选项表示模式被视为固定字符串而不是正则表达式。-G, --basic-regexp&#xff1a;此选项表示模式为基础正则表达式。这是默认的模式…

HFSS笔记/信号完整性分析(二)——软件仿真设置大全

文章目录 1、多核运算设置1.1 如何设置1.2 如何查看自己电脑的core呢&#xff1f;1.3 查看求解的频点 2、求解模式设置Driven Terminal vs Driven modal 3、Design settings4、自适应网格划分5、更改字体设置 仅做笔记整理与分享。 1、多核运算设置 多核运算只对扫频才有效果&…

如何用GPT进行数据处理?

详情点击链接&#xff1a;如何用GPT进行数据处理&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二定制自己…

HarmonyOS NEXT鸿蒙星河版发布

1月18日,在深圳举行的“鸿蒙生态千帆启航仪式”上,华为常务董事、终端BG CEO余承东宣布HarmonyOS NEXT鸿蒙星河版面向开发者开放申请。鸿蒙星河版将实现原生精致、原生易用、原生流畅、原生安全、原生智能、原生互联6大极致原生体验。 并且,华为在 1 月 15 日开启了HarmonyO…

稳定币智能分析:未来加密领域策略的关键!

随着 DeFi 和代币化改变金融领域&#xff0c;稳定币成为传统金融系统与新兴区块链之间的关键桥梁。但要在新兴的加密经济中准确评估稳定币的影响&#xff0c;需要一种全新的分析工具。 Token Explorer 是一款强大的稳定币分析工具&#xff0c;它能够追踪关键稳定币指标&#x…

50道SQL练习题及答案与详细分析

数据表介绍 --1.学生表 Student(SId,Sname,Sage,Ssex) --SId 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 --2.课程表 Course(CId,Cname,TId) --CId 课程编号,Cname 课程名称,TId 教师编号 --3.教师表 Teacher(TId,Tname) --TId 教师编号,Tname 教师姓名 --4.成绩…

抽象类(没有对象)之引用对象失败之谜

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;&#x1f468;&#x1f3fb;‍&#x1f393;告别&#xff0c;今天 &#x1f4d4;高质量专栏 &#xff1a;☕java趣味之旅 欢迎&#x1f64f;点赞&#x1f5e3;️评论&#x1f4e5;收藏&#x1f493;关注 &#x1f496;衷心的希…

从技术大会到面试舞台:程序猿的蜕变之旅!

在这个技术日新月异的时代&#xff0c;程序员们需要不断地学习和提升自己的技能。 参加技术大会&#xff0c;无疑是程序员们拓宽视野、提升技能的重要途径之一。然而&#xff0c;技术大会只是程序员成长的一部分&#xff0c;掌握面试技巧同样至关重要。只有将这两者完美结合&a…

2024年回炉计划之排序算法(一)

算法是计算机科学和信息技术中的重要领域&#xff0c;涉及到问题求解和数据处理的方法。要学习算法&#xff0c;你可能需要掌握以下一些基本知识&#xff1a; 基本数据结构&#xff1a; 了解和熟练使用各种数据结构&#xff0c;如数组、链表、栈、队列、树和图等。数据结构是算…

[一]ffmpeg音视频解码

[一]ffmpeg音视频解码 一.编译ffmpeg1.安装vmware虚拟机2.vmware虚拟机安装linux操作系统3.安装ftp和fshell软件4.在Ubuntu&#xff08;Linux&#xff09;中编译Android平台的FFmpeg&#xff08; arm和x86 &#xff09;5.解压FFmpeg6.Android编译脚本&#xff08;1&#xff09;…

军事智能中的深度强化学习不同于传统的深度强化学习

在军事智能中&#xff0c;“诡”和“诈”是两个最重要的概念。 “诡”变指的是智能体通过采取一些不可预测或复杂的变化策略来获得优势。诡变可能包括逃避对手的观察或引诱对手采取不利的行动。智能体可以使用诡变来欺骗对手&#xff0c;使其做出错误的决策或暴露其策略。 “诈…

C# WebApi传参及Postman调试

概述 欢迎来到本文&#xff0c;本篇文章将会探讨C# WebApi中传递参数的方法。在WebApi中&#xff0c;参数传递是一个非常重要的概念&#xff0c;因为它使得我们能够从客户端获取数据&#xff0c;并将数据传递到服务器端进行处理。WebApi是一种使用HTTP协议进行通信的RESTful服…

网络安全产品之认识WEB应用防火墙

随着B/S架构的广泛应用&#xff0c;Web应用的功能越来越丰富&#xff0c;蕴含着越来越有价值的信息&#xff0c;应用程序漏洞被恶意利用的可能性越来越大&#xff0c;因此成为了黑客主要的攻击目标。传统防火墙无法解析HTTP应用层的细节&#xff0c;对规则的过滤过于死板&#…

【面试合集】说说什么是进程?什么是线程?区别?

面试官&#xff1a;说说什么是进程&#xff1f;什么是线程&#xff1f;区别&#xff1f; 一、进程 操作系统中最核心的概念就是进程&#xff0c;进程是对正在运行中的程序的一个抽象&#xff0c;是系统进行资源分配和调度的基本单位 操作系统的其他所有内容都是围绕着进程展开…

[足式机器人]Part2 Dr. CAN学习笔记- Kalman Filter卡尔曼滤波器Ch05

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记 - Kalman Filter卡尔曼滤波器 Ch05 1. Recursive Algirithm 递归算法2. Data Fusion 数据融合Covarince Matrix协方差矩阵State Space状态空间方程 Observation观测器3. Step by step : Deriatio…

【JVM】强软弱虚引用详细解释

​ &#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;JVM ⛳️ 功不唐捐&#xff0c;玉汝于成 ​ 目录 前言 正文 1、强引用 2、软引用 3、弱引用 4、虚引用 结语 我的其他博客 前言 在Java中&#xff0c;引用类型对于对象的生命周期管…

SG-9101CGA(汽车+125°C可编程晶体振荡器)

SG-9101CGA是用于汽车CMOS输出的可编程晶体振荡器&#xff0c;彩用2.5 x 2.0 (mm)封装&#xff0c;0.67 MHz至170 MHz频率范围、工作温度范围为-40℃~125℃&#xff0c;符合车规级晶振&#xff0c;无铅&#xff0c;绿色环保&#xff0c;满足汽车工业标准&#xff0c;电源电压范…

Django初创shop应用

创建项目和应用 启动一个名为mysite的新项目&#xff0c;其中包含一个名为shop的应用程序。 打开shell并运行以下命令&#xff1a;django-admin startproject mysite cd myshop/ django-admin startapp shop 将shop应用程序添加到INSTALLED_APPS 编辑项目的settings.py文件&am…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(9)-Fiddler如何设置捕获Https会话

1.简介 由于近几年来各大网站越来越注重安全性都改成了https协议&#xff0c;不像前十几年前直接是http协议直接裸奔在互联网。还有的小伙伴或者童鞋们按照上一篇宏哥的配置都配置好了&#xff0c;想大展身手抓一下百度的包&#xff0c;结果一试傻眼了&#xff0c;竟然毛都没有…