链表中快慢指针的应用

news/2024/5/17 20:50:58/文章来源:https://blog.csdn.net/m0_50987960/article/details/127969821

目录

一、链表的中间结点

二、回文链表

三、链表中倒数第K个结点

四、删除链表的倒数第n个结点 

五、环形链表

 六、环形链表Ⅱ


一、链表的中间结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。

 先设置两个low和fast都指向head的结点。

 现在是寻找中间结点,可以让fast一下子走两个结点,low走一个结点,两点同时向前进。

 当走到这儿的时候,会发现fast不能再继续走两步了,二low此时就是整个链表的中间结点。

这并不是一个巧合,此时就相同的时间t内,low的速度成为v,fast指针的速度为2v,low走了vt,fast走了2vt==链表长度,所以low走过的长为链表长度的一半,就是中间位置。所以整个循环的种植条件就是fast != null && fast.next != null,只要fast还能继续向后走,low就不是中间位置。

这种方法可以用来寻找链表的任意位置。

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

二、回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

回文链表问题 = 反转链表 + 找到链表中间结点问题。

当我们已经找到中间结点mid时,把mid当做头结点,将剩下的链表反转称为l2,再与以head为头结点的链表遍历进行比较,所以这个时候循环的终止条件就是l2!=null。

 运用第一题中的方法能成功找到mid结点,然后成功反转后是这样的。

 这是就可以创建循环,然后head和l2的值相互比较,如果有一个不相同那么直接返回false,判断相同过后,head和l2继续向后移动,比较下一个。直到循环退出,则证明该链表是回文链表,返回true。

    public boolean isPalindrome(ListNode head) {ListNode mid = middleNode(head);ListNode l2 = reverseList(mid);while (l2 != null) {if (head.val != l2.val) {return false;}head = head.next;l2 = l2.next;}return true;}public ListNode middleNode(ListNode head) {ListNode low = head;ListNode fast = head;while(fast != null && fast.next != null){fast = fast.next.next;low = low.next;}return low;}public ListNode reverseList(ListNode head) {if (head == null || head.next == null) {return head;}ListNode prev = null;ListNode cur = head;while (cur != null) {ListNode next = cur.next;cur.next = prev;prev = cur;cur = next;}return prev;}

三、链表中倒数第K个结点

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有5个节点,从头节点开始,它们的值依次是1、2、3 、4、5,这个链表的倒数第2个节点是值为4的节点。

有了快慢指针的定义,我们可以先让sec走k步,然后prev和sec一起向前走,当sec为空了,prev当前的值就是倒数第k个结点了。

 刚开始时,prev和sec都在head的位置上,进入while循环中,当i<k时,只有sec可以向后移动。

当i==k时,sec已经比prev先走了k步,所以sec和prev都可以向后移动了。

 当sec走到最后时,sec==null,所以整个循环跳出,这就是循环的终止条件,这个时候的prev结点就是倒数第k个结点。

    public ListNode getKthFromEnd(ListNode head, int k) {ListNode prev = head;ListNode sec = head;int i = 0;while(sec!=null){if(i>=k){prev = prev.next;}i++;sec = sec.next;}return prev;}

四、删除链表的倒数第n个结点 

给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

这种情况就不能找到倒数第n个结点,要找到它的前驱结点。然后进行删除操作。所以这道题就是前驱结点+删除节点问题,所以我们需要自己创造一个前驱结点,node和prev都指向这个前驱结点,x也指向,最终由x来输出连链表。

 有了第三道题,这道题就很好解决了,这道题只需要让prev比node多走n+1步即可。

 当prev已经多走了n+1步时,node也可以开始走了,两者一起继续向前进直到prev==null。

 这时prev已经为空了,node就是倒数第n个结点的前驱结点,这时只需要让node.next = node.next.next,就成功删除需要删除的结点了。但是有个特殊情况那就是node.next还是head没有进入循环,这时如果直接将按照正常思路,那么还是不能删除第一个元素,所以需要排除这种情况直接让x.next = node.next.next,最后返回x。

public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode prev = new ListNode(-1);ListNode node = new ListNode(-1);ListNode x = new ListNode(-1);x.next = head;prev.next = head;node.next = head;int i = 0;while(prev!=null){if(i>n){node = node.next;}i++;prev = prev.next;}if(node.next == head){x.next = node.next.next;}else{node.next = node.next.next;}return x.next;}

五、环形链表

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

 这道题运用到了跑步比赛中的套圈知识,当你和同学一起跑步,他的速度是你的两倍,那么你和同学一定会在某一时刻相遇。

所以就设置一个node一个prev同时从头结点向后移动,prev每次走两个,node每次走一个。 

 移动过后会发现,node和prev真的会重合,所以这个时候这个链表就是有环的。在代码中这个快慢指针的追逐直到prev==null || prev.next==null时才会停止,这个时候链表是没有环的,prev首先到达了尾部。

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

 六、环形链表Ⅱ

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

 第一个叉号是意味着环的入口,第二个叉号意味着用快慢指针相遇的结点,b就相当于慢指针在环内走的长度,c相当于环剩下的长度,a就是进环之前的长度。那么low走的长度是a+b。fast走了多少个环不确定就设置走了n个环,所以fast走的长度是a+b+n(b+c)。

low的速度为v,fast的速度为2v,在相同时间t时,fast走的长度是low的2倍,所以2(a+b) = a+b+n(b+c),所以a = (n-1)(b+c)+c。所以当low和fast相遇后,设置一个third从头结点开始和low一起向后遍历,low再跑n-1圈后会一定会和third在环的入口相遇。

 结论:带环链表,快指针一次走两步,慢指针一次走一步,相遇之后,引入第三个指针从head开始向后遍历,则第三个指针一定会和慢指针在环的入口相遇。

 在第五题中得出low和fast相遇的点如图,如果此刻fast==null|| fast.next==null则证明链表没有环直接返回空即可。现在确定链表肯定有环了,创建third和low一起向后遍历,直到他俩相等。

 如图在这种情况下只要再走一步third和low就相遇了,所以返回当前的third,就得到了环的入口。

    public ListNode detectCycle(ListNode head) {if(head==null||head.next==null){return null;}ListNode low = head;ListNode fast = head;ListNode third = head;while(fast.next!=null&&fast!=null){fast = fast.next.next;low = low.next;if(low==fast){break;}}if(fast==null|| fast.next==null){return null;}while(third!=low){third = third.next;low = low.next;}return third;}

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

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

相关文章

基于Spring Cloud的架构使用学习升级之路

引言 Spring Cloud全家桶用了挺长时间了&#xff0c;很长一段时间都是基于已有的架构进行需求研发。今年成为团队技术负责人&#xff0c;承担了新的项目&#xff0c;这是很好的一个机会&#xff0c;于是开启了项目架构升级之路。 架构&#xff0c;是团队项目的根基。在一个团…

为什么开源在线表单工具能做好数据管理?

在数字化时代&#xff0c;数据的有效应用和管理可以说是企业的无形资产&#xff0c;做好数据管理既能提升办公效率&#xff0c;又能帮助企业从规律的数字化管理中获取高效的管理策略。那么&#xff0c;什么样的开源在线表单工具可以实现这一目的&#xff1f;对于企业而言&#…

token的使用

一&#xff1a;什么是token及token的作用&#xff1f; 1.什么是token&#xff1f; Token是首次登录时&#xff0c;由服务器下发&#xff0c;作为客户端进行请求时的一个令牌。当请求后台方法时&#xff0c;用于身份验证 当第一次登录后&#xff0c;服务器生成一个Token便将此…

【SpringBoot】SpringBoot+SpringSecurity+CAS实现单点登录

文章目录一.CAS的概述1.SSO2.CAS3.概念二.CAS的流程三.CAS服务端部署1.下载地址2.源码打包3.部署运行4. java.io.FileNotFoundException: \etc\cas\thekeystore (系统找不到指定的文件。)四.CAS的定制1.定制数据源2.兼容 HTTP3.定制登录页五.SpringBoot集成CAS1.工程创建2.导入…

【OpenCV 例程 300篇】248. 特征描述之HOG描述符

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】248. 特征描述之HOG描述符 1. 方向梯度直方图 方向梯度直方图&#xff08;Histogram of Oriented Gradient, HOG&#xff09;使用梯度方向的分布作为特征来构造描述符&#xff0c;应用非常广泛。 梯…

十万部冷知识:“澳大利亚”为什么属于亚洲球队?

在2022年卡塔尔世界杯上&#xff0c;总共有6支球队入围&#xff0c;他们分别是日本队&#xff0c;韩国队&#xff0c;沙特队&#xff0c;伊朗队&#xff0c;澳大利亚队&#xff0c;还有就是东道主卡塔尔队。但是我们知道&#xff0c;澳大利亚&#xff0c;并不是亚洲的国家&…

前端面试题(JS部分)

目录一&#xff0c; 数据类型1&#xff0c;什么是引用类型&#xff0c;值类型&#xff1f;2&#xff0c;哪些值类型3&#xff0c;哪些引用类型4&#xff0c;判断数据类型5&#xff0c;typeof判断6&#xff0c;instanceof7&#xff0c;construtor二&#xff0c;浅拷贝 / 深拷贝1…

在阿里云 ACK 上部署 EMQX MQTT 服务器集群

云进入以「应用为中心」的云原生阶段&#xff0c;Operator 模式的出现&#xff0c;则为 Kubernetes 中的自动化任务创建配置与管理提供了一套行之有效的标准规范。通过将运维知识固化成高级语言 Go/Java 代码&#xff0c;使得运维知识可以像普通软件一样交付&#xff0c;并能支…

Jmeter的使用说明

一、安装Jmeter工具 链接&#xff1a;https://pan.baidu.com/s/1ZYc15eq9DO-r0ChKHxMXlg?pwdckcd 提取码&#xff1a;ckcd --来自百度网盘超级会员V5的分享二、Jmeter的常用元器件说明 jmeter八大元件件&#xff1a;取样器&#xff0c;前置处理器&#xff0c;后置处理器&a…

MySQL的高阶学习:索引、B+树

1.索引 索引是一种数据结构&#xff0c;如果没有索引&#xff0c;查找一个数据就需要从第一页开始全局检索直至找到需要的数据&#xff0c;有了索引可以先在目录中根据拼音查找到该数据所在的页数&#xff0c;因此通过索引可以大大减少了查询时间。 索引有两种存储类型&#xf…

汽车安全气囊设计?Abaqus/Part特殊建模方法-附案例step-by-step教学

作者 | 邓怡超 Abaqus/Part基于特征的建模功能可以说非常齐全&#xff0c;基本能够满足一般的分析要求&#xff0c;更复杂的模型则可以通过与专业三维建模软件之间的接口来导入&#xff0c;今天要说的是部件的另外一种建模方法。 有一种类型的分析&#xff0c;部件自身的初始…

Linux基础8 - 网络配置

Linux基础8 - 网络配置 一、网络连接的三种方式 Vmware为我们提供了三种网络工作模式&#xff0c;它们分别是&#xff1a;Bridged&#xff08;桥接模式&#xff09;、NAT&#xff08;网络地址转换模式&#xff09;、Host-Only&#xff08;仅主机模式&#xff09;。 1、桥接模式…

zabbix日志监控:操作系统、业务系统、文件大小、多行日志

zabbix日志监控&#xff1a;操作系统、业务系统、文件大小、多行日志 目录1 监控操作系统日志2 监控业务系统日志具体要求&#xff1a;分析&#xff1a;操作&#xff1a;3 监控日志文件大小&#xff08;1&#xff09;在被管主机当中安装agent&#xff08;2&#xff09;在以下za…

Activity、Fragment之间的传值

1、Activity和Activity之间传值 1、使用Intent 2、使用Intent结合Bundle IntentBundle 3、传自定义对象实现&#xff08;实现Serialzable接口&#xff0c;性能较差&#xff0c;系统自动处理&#xff09; 传自定义对象 4、传自定义对象&#xff08;实现Parcelable,性能较好…

操作系统复习【面试】

操作系统复习【面试】前言推荐操作系统复习第一章 操作系统引论 11.3 操作系统的基本特性 141.3.1 并发1.3.2 共享1.3.3 虚拟1.3.4 异步1.4 操作系统的主要功能 171.4.1 处理机管理功能1.4.2 存储器管理功能1.4.3 设备管理功能1.4.4 文件管理功能1.4.5 操作系统和用户之间的接口…

MySQL Hash Join前世今生

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a;nw MySQL Hash Join前世今生 因工作需要&#xff0c;对MySQL Hash Join的内部实现做了一些探索和实践&#x…

内部类_Java

作者&#xff1a;爱塔居的博客_CSDN博客-JavaSE领域博主 专栏&#xff1a;JavaSE 文章目录 目录 文章目录 一、内部类的概念 二、内部类的分类 1.静态内部类&#xff08;被static修饰&#xff09; 2.非静态内部类 3.局部内部类 4.匿名内部类 一、内部类的概念 当一个事物…

【微服务解耦之事件启动】Spring Boot 解耦之事件驱动

一、前言 简介&#xff1a; 在项目实际开发过程中&#xff0c;我们有很多这样的业务场景&#xff1a;一个事务中处理完一个业务逻辑后需要跟着处理另外一个业务逻辑&#xff0c;伪码大致如下&#xff1a; Service public class ProductServiceImpl {...public void saveProdu…

ggplot2 | 世界杯赛程的可视化就交给我吧!~

11. 写在前面 昨天卡塔尔&#x1f1f6;&#x1f1e6;输了比赛真是让人大跌眼镜啊&#x1f631;&#xff0c;打破了世界杯东道主必胜的神律&#xff0c;也不知道王子们是怎么想的。&#x1f923; 今天是英格兰&#x1f3f4;&#xe0067;&#xe0062;&#xe0065;&#xe006e…

WebRTC Pacer

目录 一. 前言 二. WebRTC Pacer 1. 数据包传入Pacer模块的队列 2. Pacer模块取出队列的包发送 &#xff08;1&#xff09;什么时候取出数据包发送 &#xff08;2&#xff09;每次发送多少数据量 &#xff08;3&#xff09;避免引入较大延时的处理方法 一. 前言 实时音视…