当前位置: 首页 > article >正文

【快慢指针】突破环形链表

 

 🚀个人主页:一颗小谷粒 

 🚀所属专栏:力扣刷题

很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~

目录

一、链表的中间结点

1.1 题目要求

1.2 图解分析

1.3 Java代码实现 

1.4 复杂度分析

二、环形链表 I

2.1 题目要求

2.2 算法分析

2.3 Java代码实现

2.4 复杂度分析

三. 环形链表 II

3.1 题目要求

3.2 图解分析

3.3 Java代码实现

3.4 复杂度分析 

四、总结 


一、链表的中间结点

 

首先,让我们通过一道找链表的中间结点的题目来认识一下什么是快慢指针,以及它在题中是如何运用的!

1.1 题目要求

leetcode876.链表的中间结点 这道题就可以使用快慢指针来解答,题目如下:

876. 链表的中间结点 - 力扣(LeetCode)

1.2 图解分析

我们用两个指针指向链表的头结点,一个叫快指针(fast),一个叫慢指针(slow),每次循环慢指针走一步,快指针走两步。

若链表长度为3 ,一次循环后结束,如图:

若链表长度为5 ,两次循环后结束,如图:

链表长度为奇数的时候,若快指针在最后一个节点,那么慢指针一定在中间节点 

那么链表长度为偶数呢?

以链表长度为2举例,一次循环后结束,如图:

 若链表长度为4 ,两次循环后结束,如图:

 对于偶数节点,如果快指针指向空,那么慢指针一定在中间节点上

 综合两种情况,当快指针指向空,或者它的下一个节点指向空,这个时候就退出循环

1.3 Java代码实现 

    public ListNode middleNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

1.4 复杂度分析

  • 当快指针走到链表末尾的时候循环就结束了,所以时间复杂度是O(n)的。
  • 空间复杂度由于我们只用到若个额外变量,所以它是O(1)的。

OK!通过这道题相信大家对快慢指针已经有了一个基本的认识了~~

二、环形链表 I

2.1 题目要求

leetcode.141 题目如下:

141. 环形链表 - 力扣(LeetCode)

2.2 算法分析

慢指针每次循环走一步,如果图中有环的话,那么慢指针一定会进入到环中,由于快指针相对于慢指针每次循环多走了一步,所以快指针肯定会与慢指针相遇。

所以我们只需要在第一题代码每次循环时判断快慢指针是否会相遇即可! 如果链表成环,快慢指针一定会相遇!

2.3 Java代码实现

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

2.4 复杂度分析

  • 由于慢指针进入环后,我们的循环次数是小于环的长度的,所以时间复杂度是O(n)的。
  • 空间复杂度O(1)的,因为我们只用到若个额外变量。

三. 环形链表 II

3.1 题目要求

leetcode.142 题目如下:

142. 环形链表 II - 力扣(LeetCode)

这个题与141相比,不仅要判断是否有环,还要找到环的入口!

3.2 图解分析

如图所示:

  • 环长 = b + c
  • 慢指针移动距离 = a + b
  • 快指针移动距离 = a + k(b+c) + b

由于快指针移动距离是慢指针的两倍 ,所以推导得:

 

那么 a - c = (k - 1)(b +c) 意味着什么呢? 

slow 从相遇点出发,head从头节点出发,走c步后,slow在入口,head 到入口的距离也恰好是环长的倍数,继续走,两者必然会在入口相遇 ! 

这里有个结论:当快慢指针相遇时,慢指针还没有走完一整圈  

大家可以在本子上画图来一步步模拟这个过程,相信你会理解的!

3.3 Java代码实现

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

3.4 复杂度分析 

  • 时间:O(n)
  • 空间:O(1)

四、总结 

这三个题都有相似之处,都运用了快慢指针的方法来解决,第一遍做可能无法体会,反复琢磨,相信你会理解它的原理,顿悟其中的奥妙!



 本次的分享就到此为止了,希望我的分享能给您带来帮助,创作不易也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见

 博主wx:g2279605572 


http://www.kler.cn/news/309388.html

相关文章:

  • 企微无限群发:精准营销与合规边界的探索
  • 性能测试的五大目标
  • 基于yolov8的舌苔识别检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
  • Meme“淘金”热潮下:Meme发射平台的安全风险分析
  • Python文本数据切分及HTML数据处理
  • bootstrapping in the main distro: listing WSL distros: running WSL xxxx
  • DevOps工程师的职业发展路径
  • 荣耀时刻|Anzo Capital 闪耀2024国际金融产业博览会
  • 尚航科技受邀出席腾讯全球数字生态大会,并重磅发布云智算中心共建计划
  • flutter widget.onPressed回调无效
  • 学会这个AI副业,小白也能轻松副业变现100+!
  • python内置模块pathlib.Path类操作目录和文件
  • 游戏各个知识小点汇总
  • web安全测试入门
  • 如何用安卓玩Java版Minecraft,安卓手机安装我的世界Java版游戏的教程
  • LabVIEW提高开发效率技巧----VI服务器和动态调用
  • 【Webpack--000】了解Webpack
  • 如何查看微信聊天记录?四种实用方法查询微信聊天记录,赶快码住!
  • 分析内存动态加载PE文件
  • 第十一章 【后端】商品分类管理微服务(11.3)——商品管理模块 yumi-etms-goods
  • NLP与文本生成:使用GPT模型构建自动写作系统
  • 建筑机器人通用操作系统设计方案
  • Js中call、apply和bind的区别
  • C语言 | Leetcode C语言题解之第412题Fizz Buzz
  • 鸿蒙开发(NEXT/API 12)【网络连接管理】 网络篇
  • 实现浏览器的下拉加载功能(类似知乎)
  • maven项目下使用Jacoco测试覆盖率
  • vue3使用panolens.js实现全景,带有上一个下一个,全屏功能
  • 风力发电厂智能化转型5G工业路由器物联网应用解决方案
  • 大数据-133 - ClickHouse 基础概述 全面了解