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

news2024/10/6 20:41:01

🔥博客主页: 小扳_-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;
    }
    
}

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

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

相关文章

Android修行手册 - 阴影效果的几种实现以及一些特别注意点

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列点击跳转>ChatGPT和AIGC &#x1f449;关于作者 专…

一本了解生成式人工智能

上周&#xff0c;发了一篇关于大语言模型图数据库技术相结合的文章&#xff0c;引起了很多朋友的兴趣。当然了&#xff0c;这项技术本身就让俺们很兴奋&#xff0c;比如我就是从事图研发的&#xff0c;当然会非常关注它在图领域的应用与相互促就啦。 纵观人类文明历史&#xff…

uniapp——项目day05

购物车页面 结算区域 把结算区域封装为组件 1. 在 components 目录中&#xff0c;新建 my-settle 结算组件&#xff1a; 2. 初始化 my-settle 组件的基本结构和样式&#xff1a; <template><view class"my-settle-container">结算组件</view> …

代码随想录算法训练营第21天|530.二叉搜索树的最小绝对差 501.二叉搜索树中的众数 236. 二叉树的最近公共祖先

JAVA代码编写 530.二叉搜索树的最小绝对差 给你一个二叉搜索树的根节点 root &#xff0c;返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数&#xff0c;其数值等于两值之差的绝对值。 示例 1&#xff1a; 输入&#xff1a;root [4,2,6,1,3] 输出&#xff1a;1…

内网穿透工具NPS(保姆级教程)

前言&#xff1a; 有时候我们受限于硬件设备和网络的的问题&#xff0c;无法将内网的大容量、高性能存储设备或计算设备对外访问。这个时候就会变的特别苦恼&#xff0c;上云呢成本太大&#xff0c;不用云呢公网又无法直接访问&#xff0c;这个时候怎么办呢&#xff0c;NPS它来…

华为云优惠券介绍、领取入口及使用教程

华为云是华为的云服务品牌&#xff0c;致力于为用户提供一站式云计算基础设施服务。为了吸引用户&#xff0c;华为云经常推出各种优惠活动&#xff0c;其中就包括优惠券的发放&#xff0c;下面将为大家详细介绍华为云优惠券的作用、领取入口以及使用教程。 一、华为云优惠券介绍…

SDL2 播放视频文件(MP4)

1.简介 这里引入FFmpeg库&#xff0c;获取视频流数据&#xff0c;然后通过FFmpeg将视频流解码成YUV原始数据&#xff0c;再将YUV数据送入到SDL库中实现视频播放。 2.FFmpeg的操作流程 注册API&#xff1a;av_register_all()构建输入AVFormatContext上下文&#xff1a;avform…

如何检查 Docker 和 Kubernetes 是否可以访问外部网络,特别是用于拉取镜像的仓库?

要检查 Docker 和 Kubernetes 是否可以访问外部网络&#xff0c;尤其是用于拉取容器镜像的仓库&#xff0c;您可以按照以下步骤进行&#xff1a; 1. 检查节点的网络连接 首先&#xff0c;您需要确保 Kubernetes 节点能够访问外部网络。这可以通过在节点上执行 ping 命令来测试…

11月第2周榜单丨飞瓜数据B站UP主排行榜榜单(B站平台)发布!

飞瓜轻数发布2023年11月6日-11月12日飞瓜数据UP主排行榜&#xff08;B站平台&#xff09;&#xff0c;通过充电数、涨粉数、成长指数、带货数据等维度来体现UP主账号成长的情况&#xff0c;为用户提供B站号综合价值的数据参考&#xff0c;根据UP主成长情况用户能够快速找到运营…

Linux安装jdk1.8教程(服务器可以访问网络)

文章目录 前言创建安装目录查看是否安装过下载解压配置环境变量查看是否安装成功 前言 本教程介绍了一种快捷的jdk1.8安装方法。 创建安装目录 mkdir -p /opt/software // 这是我自己的安装目录&#xff0c;根据自己的习惯确定查看是否安装过 rpm -qa | grep -i jdk需要注意…

2023年人工智能还好找工作吗?

人工智能的就业形势并不严峻&#xff0c;相反&#xff0c;很多岗位都是供不应求的状态&#xff0c;可以看一下下面的官方数据。 脉脉高聘人才智库发布《2023泛人工智能人才洞察》&#xff0c;对23年1-8月的人工智能行业现状进行了分析总结。 人工智能相关岗位数据&#xff1a…

探索游戏公司跨部门合作的项目管理工具选择

为了实现出色的用户体验&#xff0c;游戏公司需要强大的研发能力和发行运营经验。通常情况下&#xff0c;游戏公司内部有多个独立工作的研发部门和发行部门&#xff0c;它们需要跨部门协作。随着公司快速发展和游戏项目增加&#xff0c;游戏公司迫切需要一套适用于特殊协作流程…

vue中ref的用法

vue中ref的用法 在项目中使用ref时有时候直接取值,有时候返回的却是一个数组,不知其中缘由,后查了一下ref用法,所以总结一下. 1.绑定在dom元素上时&#xff0c;用起来与id差不多&#xff0c;通过this.$refs来调用: <div id"passCarEchart" ref"passCarEch…

浙江大学数据结构陈越 第一讲 数据结构和算法

数据结构 数据结构是计算机科学中用来组织和存储数据的方式。它可以理解为一种组织数据的方式&#xff0c;能够有效地管理和操作数据&#xff0c;以及提供对数据进行存储、检索、更新和删除等操作的方法。常见的数据结构包括数组、链表、栈、队列、树和图等&#xff0c;它们各自…

竞赛选题 深度学习的视频多目标跟踪实现

文章目录 1 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的视频多目标跟踪实现 …

vue项目使用electron打包exe桌面程序

首先在vue项目中cmd进入终端&#xff0c;然后第一次下载electron依赖需要切换镜像&#xff0c;否则下载得很慢很慢&#xff0c;在终端中输入以下两个命令 将 Electron Builder Binaries 的镜像源设置为淘宝的 npm 镜像源。这同样用于提升 Electron Builder 相关包的下载速度。 …

Android 摇一摇功能实现,重力加速度大于15

最近接到需求实现摇一摇需求&#xff0c;不过这个法律限制的很严格&#xff0c;属于敏感地带&#xff0c;实现后又被叫停了。 法律要求&#xff1a; 如果按照规定&#xff0c;操作时间不少于3s就基本没什么跳转了。 实现的话&#xff0c;只考虑了第一条&#xff0c;即&#…

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

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

Java 轻松删除PDF指定页、空白页 (免费工具分享)

对PDF页面的增删通常需要借助专门的工具&#xff0c;而这些工具一般需要付费才能使用。那么我们可以通过Java代码免费实现这一功能吗&#xff1f;答案是肯定的。这篇文章就教大家如何使用一个免费的国产Java库来删除PDF中的指定页面或者删除PDF中的空白页。 使用Java快速删除PD…

git push 报错 The requested URL returned error: 500

今天gitpush时报错The requested URL returned error: 500 看报错应该是本地和gitlab服务器之间通信的问题&#xff0c;登录gitlab网站查看 登录时报错无法通过ldapadmin认证&#xff0c;ldap服务器连接失败。 首先&#xff0c;登录ldap服务器&#xff0c;查看是否是ldap服务…