Java 算法篇-链表的经典算法:根据值删除节点、删除倒数第 n 个节点

🔥博客主页: 小扳_-CSDN博客
❤感谢大家点赞👍收藏⭐评论✍
  

 

 

 

文章目录

        1.0 链表的创建

        2.0 链表的经典算法 - 根据值来删除节点

        2.1 根据值来删除节点 - 遍历链表来实现

        2.2 根据值来删除节点 - 递归实现

        3.0 链表的经典算法 - 删除倒数第 n 个节点

        3.1 删除倒数第 n 个节点 - 使用递归来实现

        3.2 删除倒数第 n 个节点 - 快慢指针来实现

        4.0 本篇链表的经典算法的完整实现代码


        1.0 链表的创建

        为了更好的讲解算法的具体内容,先创建好链表,实现一个带哨兵的单链表

代码如下:

import java.util.Iterator;public class List implements Iterable<Integer>{private  Node hand;static class Node {public int value;public Node next;public Node() {}public Node(int value, Node next) {this.value = value;this.next = next;}}public List() {hand = new Node(0,null);}@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {Node p = hand.next;@Overridepublic boolean hasNext() {return p != null;}@Overridepublic Integer next() {int value = p.value;p = p.next;return value;}};}}

        之前的篇章都有讲解过以上的每一个方法及其作用,需要了解的点击一下链接:

Java 算法篇-深入了解单链表的反转(实现:用 5 种方式来具体实现)-CSDN博客

        2.0 链表的经典算法 - 根据值来删除节点

        介绍两种方式来实现该算法:

        一、遍历链表来实现

        二、使用递归来实现

        2.1 根据值来删除节点 - 遍历链表来实现

        实现思路为:设置两个节点分别为: o1, 一开始指向哨兵节点。o2,一开始指向头节点(也就是 哨兵节点指向的节点),想让 o2 节点往后走一步,来判断当前 o2 的节点的值是否为需要的节点,若是,则让 o1 指向 o2.next 节点,然后 o2 = o1.next  接着往后走;若不是,则让 o1 = o2 完成赋值(意味着 o1 永远跟着 o2 节点后面,o2 永远比 o1 走前一步),接着 o2 = o2.next 往后走。循环终止的条件为,当 o2 == null 就该停止了

代码如下:

    //根据值来删除节点public void removeValue( List list, int value) {Node o1 = list.hand;Node o2 = list.hand.next;while (o2 != null) {if (o2.value == value) {o1.next = o2.next;o2 = o1.next;}else {o1 = o2;o2 = o2.next;}}}

        再讲个好理解的思路:把 o1 比作战场上的大部队,把 o2 比作地雷兵,每一次往前走的时候,都需要让地雷兵先去排雷,若前方没雷时,这时候 o1 紧跟着 o2 走过的路径;若前方发现雷时,需要排除掉,以此类推,直到走完。

        2.2 根据值来删除节点 - 递归实现

        实现的思路:先把需要删除节点的链表进行递归到底进行展示出来,也就是一直递归到底,然后在回归的时候,当 p == null 说明了已经到了链表的底部了,直接返回 null 就好了。需要来判断该节点的值是否需要删除:若不需要删除的节点,在回归的时候需要返回自己的节点,然后需要更新该节点的指向。若需要删除的节点,在回归的时候直接返回 下一个节点

代码如下:

    private Node recursion1(Node p, int value) {if (p == null) {return null;}if (p.value == value) {return recursion1(p.next, value);}else {p.next = recursion1(p.next, value);return p;}}

结合代码来具体的实现流程:

        

        3.0 链表的经典算法 - 删除倒数第 n 个节点

        介绍两种方式来实现该算法:

        一、使用递归来实现

        二、使用快慢指针来实现

        3.1 删除倒数第 n 个节点 - 使用递归来实现

        实现思路:先递出到底 p == null 返回 0 ,接着然后每一次回归都对当前的 i 进行 i++,再来判断是否 i == n,但是我们细想一下,我们得到了 i == n 这个要删除的节点是不是没有什么用,因此,我们实际需要找的节点是 n + 1,当 i == n + 1 时,就可以删除倒数第 n 个节点了 p.next = p.next.next 这样就删除了节点了。

代码如下:

    //删除倒数第 n 个节点(递归法)public List deleteCount(List list, int n) {recursion(list.hand,n);return list;}private int  recursion(Node p, int n) {if (p == null) {return 0;}int i = recursion(p.next, n);i++;if (i == n + 1) {p.next = p.next.next;}return i;}

        需要注意的是,这里一定要用带上哨兵的链表,原因是:当我要删除的节点是第一个的时候,没哨兵是完成不了这个操作的。

        3.2 删除倒数第 n 个节点 - 快慢指针来实现

        思路:先定义两个 fast、slow 快慢指针,一开的时候都指向哨兵节点,然后让 slow 先跑 n+1个节点,然后就两个指针 一起跑,循环的结束条件为: slow == null ,因为当 slow == null是,fast.next 刚好指向了要删除的节点,那么直接就用 fast.next = fast.next.next 这就把第 n 个节点删除掉了。

代码如下:

    //删除倒数第n个节点(快慢指针)public List removeFastSlowPointers(List list, int n) {list.hand = fastSlowPointers(list.hand,n);return list;}private Node fastSlowPointers(Node hand, int n) {Node temp = hand;Node fast = hand;Node slow = hand;for (int i = 0; i < n + 1; i++) {slow = slow.next;}while (slow != null) {slow = slow.next;fast = fast.next;}fast.next = fast.next.next;return temp;}

        这里需要注意的是,当要删除第 1 个节点的时候,若没有哨兵节点的时候,是完成不了这个操作的。还有需要注意的是,关于要删除第 n 个节点,实际要找到第 n+1 个节点才能对第 n 个节点进行删除。

        4.0 本篇链表的经典算法的完整实现代码

import java.util.Iterator;public class List implements Iterable<Integer>{private  Node hand;static class Node {public int value;public Node next;public Node() {}public Node(int value, Node next) {this.value = value;this.next = next;}}public List() {hand = new Node(0,null);}@Overridepublic Iterator<Integer> iterator() {return new Iterator<Integer>() {Node p = hand.next;@Overridepublic boolean hasNext() {return p != null;}@Overridepublic Integer next() {int value = p.value;p = p.next;return value;}};}//头插节点public void addFirst(int value) {hand.next = new Node(value,hand.next);}//尾插节点public void addLst(int value) {Node p = hand;while (p.next != null) {p = p.next;}p.next = new Node(value,null);}//根据值来删除节点public void removeValue( List list, int value) {Node o1 = list.hand;Node o2 = list.hand.next;while (o2 != null) {if (o2.value == value) {o1.next = o2.next;o2 = o1.next;}else {o1 = o2;o2 = o2.next;}}}//根据值来删除节点(递归实现)public List removeRecursion(List list ,int value) {Node p = list.hand.next;Node tp = recursion1(p,value);list.hand.next = tp;return list;}private Node recursion1(Node p, int value) {if (p == null) {return null;}if (p.value == value) {return recursion1(p.next, value);}else {p.next = recursion1(p.next, value);return p;}}//删除倒数第n个节点(递归法)public List deleteCount(List list, int n) {recursion(list.hand,n);return list;}private int  recursion(Node p, int n) {if (p == null) {return 0;}int i = recursion(p.next, n);i++;if (i == n + 1) {p.next = p.next.next;}return i;}//删除倒数第n个节点(快慢指针)public List removeFastSlowPointers(List list, int n) {list.hand = fastSlowPointers(list.hand,n);return list;}private Node fastSlowPointers(Node hand, int n) {Node temp = hand;Node fast = hand;Node slow = hand;for (int i = 0; i < n + 1; i++) {slow = slow.next;}while (slow != null) {slow = slow.next;fast = fast.next;}fast.next = fast.next.next;return temp;}}

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

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

相关文章

前端element的el-tooltip鼠标经过显示文字,没有文字显示空黑框问题

场景&#xff1a; 有时候在使用element的el-tooltip时会使用三元表达式&#xff0c;满足某个条件后才显示提示文字&#xff0c;否则不展示文字&#xff0c;但是却出现在在没有文字时展示了黑框&#xff0c;如下图&#xff1a; 解决方案&#xff1a; 加一个disabled便可&#…

Spring Cloud Netflix微服务组件-Eureka

CAP理论 分区容忍是能容忍一个或一部分节点挂掉后&#xff0c;整体系统也能正常工作&#xff08;就是别的节点还是活着的&#xff09;&#xff0c;所以分布式系统中P是必须要有的。比如数据库主从架构&#xff0c;主从两个节点之间需要数据同步&#xff0c;主挂了&#xff0c;…

最新PS 2024 虎标正式版来啦,附带AI神经滤镜(支持win/mac)

软件简介 文件名称 PS2024 虎标正式版 支持系统 windows、Mac 获取方式 文章底部 分享形式 百度网盘 小伙伴们&#xff0c;下午好&#xff01;今天给大家的是PS 2024 25.0虎标正式版。 PS 2024 25.0 正式版介绍 经历了多次Photoshop 2023 Beta 测试之后&#xff0c;今天…

Qt高级--(2)自定义标题栏

自定义标题栏 功能点 1.标题栏中最外层布局器使用水平布局器。 2.导航按钮、工具按钮和窗口功能按钮都是用水平布局器&#xff0c;边距和间隔可根据实际情况设置。 3.编写 QSS 样式&#xff0c;并将样式设置到窗口控件中。 4.实现最小化、最大化和关闭窗口按钮功能。 5.实现鼠…

springboot整合vue2实现简单的新增删除,整合ECharts实现图表渲染

先看效果图&#xff1a; 1.后端接口 // 查询所有商品信息 // CrossOrigin(origins "*")RequestMapping("/list1")ResponseBodypublic List<Goodsinfo> list1(){List<Goodsinfo> list goodsService.list();return list;}// 删除 // …

你绝对需要的Facebook养号攻略,教你如何养成耐用号

Facebook 可谓是大家的“老熟人”了&#xff0c;作为全球热门的社交媒体平台&#xff0c;Facebook 一直以来都是社媒营销、跨境电商的重要阵地&#xff0c;但是很多小伙伴们在注册新账号后往往忽略了一个重要的步骤&#xff0c;也是必不可少的一步&#xff0c;那就是养号&#…

【跨境电商独立站新手入门手册】

一直想要更新一个独立站的系列合集&#xff0c;用小白也看得懂的方式阐述怎么从0到1搭建并运营一个独立站&#xff0c;并且后续我也会录制成视频。 今天&#xff0c;它来了。 这是《跨境电商独立站新手入门手册》系列的第一篇。 你是否有过这样的经历&#xff1a;当你在网上浏…

vue中使用iconfont图标

1. 选择一个图标加入购物车 2、点击右上角购物车图标。点击下载代码&#xff0c;并添加至项目。 3、将下载好的代码文件放入项目中的assets目录的styles下 iconfont.css直接放在styles下 在styles目录下新建目录iconfont&#xff0c;将iconfont.ttf、iconfont.woff、iconfont…

python自动化测试selenium核心技术3种等待方式详解

这篇文章主要为大家介绍了python自动化测试selenium的核心技术三种等待方式示例详解&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步早日升职加薪 UI自动化测试过程中&#xff0c;可能会出现因测试环境不稳定、网络慢等情况&a…

安防监控系统EasyCVR平台调用hls地址生成流的时间过长,该如何解决?

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台可拓展性强、…

[工业自动化-13]:西门子S7-15xxx编程 - 分布式从站 - 硬件配置

目录 前言&#xff1a; 一、通过博图软件完成对ET200 SP分布式从站的硬件配置 二、从站组态配置的常见问题与解决 三、分布式从站与CPU的profiNet连接 3.1 概述 3.2 配置主站与从站的profinet连接 四、Profinet和普通以太网区别 4.1 概述 4.2 协议栈 五、主站与从站连…

【开源】基于JAVA的生活废品回收系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容三、界面展示3.1 登录注册3.2 资源类型&资源品类模块3.3 回收机构模块3.4 资源求购/出售/交易单模块3.5 客服咨询模块 四、免责说明 一、摘要 1.1 项目介绍 生活废品回收系统是可持续发展的解决方案&#xff0c;旨在鼓…