简单的算法思想 - 利用快慢指针解决问题 - 寻找链表中的中间节点,回文序列,倒数第k个节点 - 详解

news2024/9/22 3:58:15

文章目录

  • 1. 寻找链表中倒数第K个节点
    • 1.1. 思路分析
    • 1.2 代码实现
  • 2. 寻找链表中的中间结点
    • 2.1 思路概述
    • 2.2 代码实现
  • 3. 链表的回文结构
    • 3.1 思路分析
    • 3.2 代码实现
  • 总结

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

本文通过寻找链表中的中间节点,链表的回文序列,链表中倒数第k个节点OJ题问题,来进一步提高双指针在题中的使用,更好的扩展思路,锻炼思维;


1. 寻找链表中倒数第K个节点

题目描述

输入一个链表,输出该链表中倒数第k个结点。
输入:
1,{1,2,3,4,5}
返回值:
{5}

1.1. 思路分析

利用双指针:寻找倒数第k个节点,倒数第k个节点就会距离尾节点是k-1个单位,(尾节点的next==null),k-1这段距离是不变的 ;
可以通过 平移思想,让快指针fast先走k-1个单位,慢指针slow就会距离fast k-1个单位;
保持两节点距离不变再平移两节点(同时移动一步或几步),当快的指针指向尾节点时,slow指针对应的就是倒数第k个节点;

1.2 代码实现

代码实现具体操作:

① 可以定义两个指针fast,slow并初始化为第一个节点位置
② 让fast指针先走k-1步,这样fast与slow指针就相距k-1个位置;
③ 再让两指针一起一步一步走;(两指针之间距离保持相对静止)
④ 当fast.next == null 时,走到尾节点,此时slow所对应的位置就是倒数第K个位置;

在这里插入图片描述

代码实现

 public ListNode FindKthToTail(ListNode head,int k) {
        //k小于0或者没有节点
        if(k <= 0 || head == null) {
            return null;
        }
        ListNode fast = head;
        ListNode slow = head;
        //让fast先走k-1步
        while(k-1 != 0) {
            fast = fast.next;
            //fast不合法,超出节点个数:例如一共4个节点,要求寻找倒数第6个的位置 - err
            if(fast == null) {
                return null;
            }
            k--;
        }
        //两指针一起一步一步走;
        while(fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }

2. 寻找链表中的中间结点

题目描述:

给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
示例:
输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
输入:[1,2,3,4,5,6]
输出:此列表中的结点 4 (序列化形式:[4,5,6])

题目分析
对于奇数结点,返回中间结点即可;对于偶数结点,返回中间两个的第二个结点

2.1 思路概述

使用快慢双指针,让快指针每次走两步,慢指针每次走一步,当快指针为null时,慢指针指向的就是中间结点位置;

为什么让快指针一次走两步呢?
快指针一次走两步,慢指针一次走一步,他们的相对位移是一步,中间不会有跳过;如果快指针一次走三步,他们中间的相对位移就是二,会有遗漏的;对于上述例子第二个,如果快指针一次走三步,返回的结点是3而不是4了所以会有遗漏;

2.2 代码实现

【注】代码考注意事项
① 考虑特殊情况,没有结点或者只有一个结点
② 定义双指针fast,slow
快指针结束标志:fast == null (偶数个结点) || fast.next == null (奇数个结点)
④ 返回slow

public ListNode middleNode(ListNode head) {
        //快慢指针:快的走两步,慢的走一步
        //没有结点
        if(head == null) {
            return null;
        }
        //只有一共结点
        if(head.next == null) {
            return head;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null && fast.next != null) {//当找到slow位置时,fast结束条件
            fast = fast.next.next; //走两步
            slow = slow.next;
        }       
        return slow;
    }

3. 链表的回文结构

题目描述:

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1
返回:true

3.1 思路分析

根据题目,可知对于回文就是从左往右,和从右往左多是一样;
可以定义快慢指针先找到中间结点,从中间结点开始翻转中间结点之后的结点,这样从两头开始向中间比较值,如果都一样,就是回文序列;

奇数图示:

在这里插入图片描述

偶数图示:

在这里插入图片描述

3.2 代码实现

① 定义双指针fast,slow
② 寻找中间结点 (上述例题中有,不理解可以往前翻)
快指针走两步,慢指针走一步
③ 记录翻转结点的位置 cur
④ 翻转结点:翻转cur结点之前,需要记录cur后一个结点的位置,如果之间翻转,就会找不到之前的位置而出错( 翻转结点之前一定要记录后一个结点curNext
⑤ 比较翻转完后前后结点的值: 两个指针都向中间结点靠近,循环结束条件结束head != slow

【注】 (可参考上述图例)
对于偶数个结点情况:head.next == slow;偶数情况如果不这样使用,会发生空指针异常而出错;
对于奇数个结点情况是:head != slow

 public boolean chkPalindrome(ListNode A) {
        // write code here
        //寻找中间节点
        ListNode fast = A;
        ListNode slow = A;
        while(fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        //slow跳出来就是之间结点位置
        //记录翻转节点起始位置
        ListNode cur = slow.next;
        while(cur != null) {
            ListNode curNext = cur.next;//记录cur后面结点的位置
            cur.next = slow;// 结点翻转
            //slow,cur后移动准备下一次翻转
            slow = cur;
            cur = curNext;
        }
        //翻转完节点后,slow位于末端
        //比较前后节点的值
        while(A != slow) {
            if(A.val != slow.val) {
                return false;
            }
            //对于偶数情况:A.next == slow
            //对于奇数情况是:A != slow
            if(A.next == slow) {//偶数情况
                return true;
            }
            //A,slow向中间移动
            A = A.next;
            slow = slow.next;
        }
        //跳出循环,说明链表前后值相等
        return true;
    }

总结

✨✨✨各位读友,本篇分享到内容如果对你有帮助给个👍赞鼓励一下吧!!
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

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

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

相关文章

汽车托运网址

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 基于Web的汽车托运网站的设计与实现 网站前台&#xff1a;关于我们、联系我们、公告信息、卡车类型、卡车信息、运输评论…

【语音处理】一种增强的隐写及其在IP语音隐写中的应用(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

Effective Objective-C 2.0学习记录(一)

48.多用块枚举&#xff0c;少用for循环for循环快速枚举&#xff08;快速遍历&#xff09;基于块的遍历方式在编程中经常需要用到列举collection&#xff08;NSArray、NSDictionary、NSSet等&#xff09;中的元素&#xff0c;当前的Objective-C语言有多种办法实现此功能&#xf…

【专栏】核心篇09| 怎么保证缓存与DB的数据一致性

计算机类PDF整理&#xff1a;【详细&#xff01;&#xff01;】计算机类PDF整理 Redis专栏合集 【专栏】01| Redis夜的第一章 【专栏】基础篇02| Redis 旁路缓存的价值 【专栏】基础篇03| Redis 花样的数据结构 【专栏】基础篇04| Redis 该怎么保证数据不丢失&#xff08;上…

Python -- 模块和包

目录 1.Python中的模块 1.1 import 1.3 from...import * 1.4 as别名 2.常见的系统模块和使用 2.1 OS模块 2.2 sys模块 2.3 math模块 2.4 random模块 2.5 datetime模块 2.6 time模块 2.7 calendar模块 2.8 hashlib模块 2.9 hmac模块 2.10 copy模块 3.pip命令的使…

【机器学习---01】机器学习

文章目录1. 什么是机器学习&#xff1f;2. 机器学习分类2.1 基本分类2.2 按模型分类2.3 其他分类(不重要)3. 机器学习三要素4. 监督学习的应用(分类、标注、回归问题)1. 什么是机器学习&#xff1f; 定义&#xff1a;给定训练集D&#xff0c;让计算机从一个函数集合F {f1(x)&…

虚拟机打不开,提示“此主机不支持虚拟化实际模式”的详细解决方法

虚拟机打不开&#xff0c;提示“此主机不支持虚拟机实际模式”的解决方法 一、第一种情况安装/启动虚拟机失败&#xff0c; 在VMWare软件中&#xff0c;安装/启动虚拟机时&#xff0c;如果出以类似以下的错误提示&#xff1a; 出现该提示是由于电脑不支持虚拟化技术或是相关功…

IDEA报错:类文件具有错误的版本 61.0,应为52.0

springboot项目启动报错&#xff1a; 类文件具有错误的版本 61.0,应为52.0 请删除该文件或确保该文件位于正确的类路径子目录中 查阅了网上的很多资料&#xff0c;普遍原因说是springboot版本过高&#xff0c;高于3.0 需要在pom文件中降低版本 也有说是idea的maven配置java版…

网购商城网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a;

【Python机器学习】层次聚类AGNES、二分K-Means算法的讲解及实战演示(图文解释 附源码)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 层次聚类 在聚类算法中&#xff0c;有一类研究执行过程的算法&#xff0c;它们以其他聚类算法为基础&#xff0c;通过不同的运用方式试图达到提高效率&#xff0c;避免局部最优等目的&#xff0c;这类算法主要有网格聚类和…

easypoi导入excel空指针异常

问题描述 前端页面停留在导入页面&#xff0c;通过后端返回的接口&#xff0c;确认后端已经抛出异常查看系统调用错误日志为 java.lang.NullPointerException: nullat org.apache.poi.xssf.usermodel.XSSFClientAnchor.setCol2(XSSFClientAnchor.java:231)at org.apache.poi.…

基于EKF的四旋翼无人机姿态估计matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 卡尔曼滤波是一种高效率的递归滤波器(自回归滤波器)&#xff0c;它能够从一系列的不完全包含噪声的测量中&#xff0c;估计动态系统的状态。这种滤波方法以它的发明者鲁道夫E卡尔曼&#xff08;R…

Android koin

1.源码地址 1.源码地址 2.作用 1.让代码看起来更简洁 现在是这样创建对象的 2.解耦 我们有一个类&#xff0c;然后有100个地方使用它&#xff0c;这个时候如果我们要修改构造参数&#xff0c;加入一个参数&#xff0c;那么我们就要修改100个地方&#xff1b;如果过了一个…

怎样让chatGPT给你打工然后月入过千?

前言 chatGPT最近火出圈了&#xff0c;怎么薅一个文字模型给你打工呢&#xff1f; 这个UP给了个思路&#xff1a;哔哩哔哩 emmm有点尴尬&#xff0c;可能是热度比较高&#xff0c;b站的视频作者自己下架了。 总结一下&#xff1a; 薅的对象百度文库创作中心&#xff1a;地址…

设计模式之装饰器模式

decorator design pattern 装饰模式的概念、装饰模式的结构、装饰模式的优缺点、装饰模式的使用场景、装饰模式与代理模式的区别、装饰模式的实现示例、装饰模式的源码分析 1、装饰模式的概念 装饰模式&#xff0c;即在不改变现有对象结构的前提下&#xff0c;动态的给对象增加…

【云原生】Grafana 介绍与实战操作

文章目录一、概述二、Grafana 安装1&#xff09;下载安装2&#xff09;安装包信息3&#xff09;启动服务4&#xff09;Grafana 访问三、Grafana 功能介绍四、使用mysql存储1&#xff09;安装mysql2&#xff09;修改grafana配置1、创建grafana用户和grafana库2、修改grafana配置…

[附源码]Python计算机毕业设计Django学分制环境下本科生学业预警帮扶系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Innodb存储引擎-索引和算法(B+树索引、Cardinality、联合索引、覆盖索引、MRR优化、ICP优化、哈希索引、全文索引)

文章目录索引和算法B树索引聚集索引辅助索引B 树索引的分裂B 树索引的管理Cardinality 值B 树索引的使用联合索引覆盖索引优化器选择不使用索引的情况索引提示Multi-Range Read 优化(MRR)Index Condition Pushdown优化(ICP)哈希索引全文索引倒排索引InnoDB全文检索的实现全文检…

第一个MyBatis查询

⭐️前言⭐️ 在连接程序与数据库的工具中&#xff0c;我们之前使用的是JDBC技术&#xff0c;但是JDBC的操作流程极为繁琐&#xff0c;因此才有了更优秀框架——MyBatis&#xff0c;下边我们一起来看这个优秀框架MyBatis的操作与使用。 &#x1f349;欢迎点赞 &#x1f44d; 收…

Innodb存储引擎-锁(数据库锁的查看、快照读当前读、MVCC、自增长与锁、外键与锁、行锁、并发事务的问题、阻塞、死锁、锁升级、锁的实现)

文章目录锁lock 与latch读锁/写锁/意向锁INNODB_TRX/INNODB_LOCKS/INNODB_LOCK_WAITS一致性非锁定读(快照读)一致性锁定读(当前读)MVCC版本链Read View流程自增长与锁外键和锁行锁类型记录锁(record lock)间隙锁(gap lock)下一键锁(next-key lock)并发事务带来的问题阻塞死锁锁…