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);
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node p = hand.next;
            @Override
            public boolean hasNext() {
                return p != null;
            }

            @Override
            public 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);
    }

    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node p = hand.next;
            @Override
            public boolean hasNext() {
                return p != null;
            }

            @Override
            public 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;
    }
    
}

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

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

相关文章

Godot4.1 GDExtension 配置VisualStudio方法梳理以及快捷配置工具

写在最前 本篇教程基于之前教程&#xff0c;并且默认为Windows10&#xff0c;64位&#xff0c;Godot版本4.1.3如果遇到任何问题&#xff0c;欢迎及时提出&#xff0c;如果配置成功了请点个赞&#xff0c;球球啦。 之前教程 https://blog.csdn.net/qq_31805591/article/detai…

Java学习day12:static关键字,字符串声明,字符串常量池

声明&#xff1a;该专栏本人重新过一遍java知识点时候的笔记汇总&#xff0c;主要是每天的知识点题解&#xff0c;算是让自己巩固复习&#xff0c;也希望能给初学的朋友们一点帮助&#xff0c;大佬们不喜勿喷(抱拳了老铁&#xff01;) 往期回顾&#xff1a; Java学习day11&…

错误:CUDA error: device-side assert triggered CUDA kernel errors

对llama扩充中文词表后直接增量预训练&#xff0c;忘记设置--modules_to_save embed_tokens,lm_head,所以导致向量维度不一致&#xff0c;出现下面的错误。 1. 错误 2. 原因 出现这个错误的原因可能是因为维度或标签不一致。可以仔细排查一下。

【k8s集群搭建(二):基于虚拟机的linux的k8s集群搭建_超详细_可视化界面Dashboard安装_记录全过程踩坑记录及解决方法】

在 master 执行 # 根据 在线配置文件 创建资源 kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml设置访问端口 # 修改配置文件 找到 type&#xff0c;将 ClusterIP 改成 NodePort kubectl edit svc kubernetes-…

虾皮之家数据分析插件:知虾数据分析工具提升销量的利器

在当今的电商市场中&#xff0c;虾皮Shopee成为了许多商家的首选平台。然而&#xff0c;随着竞争的加剧&#xff0c;店铺运营变得越来越具有挑战性。如何提升销量&#xff0c;优化标题和图片&#xff0c;合理设置SKU&#xff0c;并准确跟踪店铺活动数据和竞品数据&#xff0c;已…

为什么网安人才缺口那么大,就业率却上不去?

为什么网安相关行业人才缺口还有三百多万&#xff0c;但现在却还有很多程序员找不到工作&#xff0c;难道我们又被所谓大数据骗了吗&#xff1f; 其实啊&#xff0c;造成如此现象的有以下几点原因&#xff1a;首先&#xff0c;教学青黄不接&#xff0c;因为网安属于近几年新开…

SCons

什么是构建工具&#xff08;系统&#xff09; 构建工具&#xff08;software construction tool&#xff09;是一种软件&#xff0c;它可以**根据一定的规则或指令&#xff0c;将源代码编译成可执行的二进制程序。**这是构建工具最基本也最重要的功能。 实际上构建工具的功能…

03.智慧商城——路由配置

01. 路由配置 - 一级路由 但凡是单个页面&#xff0c;独立展示的&#xff0c;都是一级路由 路由设计&#xff1a; 登录页首页架子 首页 - 二级分类页 - 二级购物车 - 二级我的 - 二级 搜索页搜索列表页商品详情页结算支付页我的订单页 router/index.js 配置一级路由&#x…

基于springboot实现一起来约苗管理系统项目【项目源码】

基于springboot实现一起来约苗平台管理系统演示 Java技术 Java是由Sun公司推出的一门跨平台的面向对象的程序设计语言。因为Java 技术具有卓越的通用性、高效性、健壮的安全性和平台移植性的特点&#xff0c;而且Java是开源的&#xff0c;拥有全世界最大的开发者专业社群&…

Hack_Kid

Hack_Kid 靶机地址&#xff1a;https://download.vulnhub.com/hackerkid/Hacker_Kid-v1.0.1.ova 一、主机发现 发现靶机IP为192.168.80.135 二、端口扫描 发现靶机开启了80、53、9999端口 三、信息收集 1.访问80端口 2.访问9999端口 根据靶场作者的提示&#xff0c;不…

未来服务器操作系统的趋势与展望

摘要&#xff1a; 随着云计算、大数据和人工智能不断的发展&#xff0c;服务器操作系统也需要随之进行新一轮的升级。本文通过分析当前服务器操作系统的现状&#xff0c;探讨了未来服务器操作系统的趋势和展望&#xff0c;并针对一些关键问题提出了解决方案。 一、引言 服务器…

老哥们平日是怎么排查线上问题的?

1、做好监控告警 如果线上出现了问题&#xff0c;我们更多的是希望由监控告警发现我们出了线上问题&#xff0c;而不是等到业务侧反馈。所以&#xff0c;我们需要对核心接口做好监控告警的功能。 2、定位报警层面 如果是业务代码层面的监控报警&#xff0c;那我们应该是可以…

PVE Win平台虚拟机下如何安装恢复自定义备份Win系统镜像ISO文件(已成功实现)

环境: Virtual Environment 7.3-3 Win s2019 UltraISO9.7 USM6.0 NTLite_v2.1.1.7917 问题描述: PVE Win平台虚拟机下如何安装恢复自定义备份Win系统镜像ISO文件 本次目标 主要是对虚拟机里面Win系统备份做成可安装ISO文件恢复至别的虚拟机或者实体机上 解决方案: …

海康Visionmaster-环境配置:MFC 二次开发环境配置方法

1 新建 MFC 工程&#xff0c;拷贝 DLL:VM\VisionMaster4.0.0\Development\V4.0.0 \ComControl\bin\x64 下的所有拷贝到项目工程输出目录下&#xff0c;如下图所示&#xff0c;项目的输出路径是 Dll 文件夹。 2 通过配置 C目录和链接器的方式配置 VM 环境 2.1 C目录下添加附加…

金蝶云星空单据体启用块粘贴

文章目录 金蝶云星空单据体启用块粘贴 金蝶云星空单据体启用块粘贴

c/c++语言算法技巧汇总大复习2

标题前面打*号的为多数考纲范围外的&#xff0c;可以选择性查看 &#x1f517;链接&#xff1a;严书代码大全 &#x1f517;链接&#xff1a;c/c语言算法技巧汇总大复习1 &#x1f517;链接&#xff1a;c/c语言算法技巧汇总大复习2 目录 Dp动态规划入门练习 青蛙跳台阶练习&…

大数据Hadoop之——部署hadoop+hive+Mysql环境(Linux)

目录 一、JDK的安装 1、安装jdk 2、配置Java环境变量 3、加载环境变量 4、进行校验 二、hadoop的集群搭建 1、hadoop的下载安装 2、配置文件设置 2.1. 配置 hadoop-env.sh 2.2. 配置 core-site.xml 2.3. 配置hdfs-site.xml 2.4. 配置 yarn-site.xml 2.5. 配置 ma…

韦东山linux驱动开发学习【常更】

1.linux目录简单介绍 2.直接运行需要在$path路径下

YOLOv7独家原创改进:最新原创WIoU_NMS改进点,改进有效可以直接当做自己的原创改进点来写,提升网络模型性能精度

💡该教程为属于《芒果书》📚系列,包含大量的原创首发改进方式, 所有文章都是全网首发原创改进内容🚀 💡本篇文章为YOLOv7独家原创改进:独家首发最新原创WIoU_NMS改进点,改进有效可以直接当做自己的原创改进点来写,提升网络模型性能精度。 💡对自己数据集改进有效…

AI大模型创意赛秘籍:3要素搞定初赛提交,3步走开发一个网站!

11月10日&#xff0c;飞桨星河社区X智海Mo平台&#xff0c;AI大模型创意应用大赛的首场培训圆满结束&#xff01;培训过程中的完整网站代码案例&#xff0c;可在报名比赛后获取。 初赛&#xff1a;1码2表3图&#xff0c;快速搞定初赛提交 培训实践营上&#xff0c;Jungle老师分…