代码随想录day02--链表

news2025/2/12 11:11:34

移除链表元素

题目

地址:https://leetcode.cn/problems/remove-linked-list-elements/description/

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

思路是使用虚拟节点的方式比较简单一些,直接定义一个虚拟节点指向头结点,在链表中移除元素就是将指针域向后移动两部就可

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
        //使用虚拟头结点方式
        ListNode dumpNode = new ListNode();
        dumpNode.next = head;
        
        //定义当前节点为虚拟节点
        ListNode cur = dumpNode;
        while(cur.next != null){
            if(cur.next.val == val){
                //移除元素
                cur.next = cur.next.next;
            }else{
                cur = cur.next;
            }
        }
        //指向虚拟节点的下一个节点即头节点
        return dumpNode.next;
    }
}

设计链表

题目

地址:https://leetcode.cn/problems/design-linked-list/description/

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

707示例

代码

class MyLinkedList {
    //链表数量
    int size;
    //虚拟头节点
    ListNode head; 

    //初始化链表
    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
    }
    
    // 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 
    public int get(int index) {
        if(index <0 || index >= size){
            return -1;
        }
        ListNode curNode = head;
        for(int i=0; i <= index; i++){
            curNode = curNode.next;
        }
        return curNode.val;
    }
    
    // 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }
    
    //将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }
    
    //将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的 末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
    public void addAtIndex(int index, int val) {
        if(index > size){
            return;
        }
        index = Math.max(0,index);
        size++;

        ListNode preNode = head;
        for(int i=0;i < index ;i++){
            preNode = preNode.next;
        }
        ListNode toAdd = new ListNode(val);
        toAdd.next = preNode.next;
        preNode.next = toAdd;
    }
    
    // 如果下标有效,则删除链表中下标为 index 的节点。
    public void deleteAtIndex(int index) {
        if(index < 0 || index >= size){
            return;
        }
        size--;
        ListNode curNode = head;
        for(int i=0 ; i < index ; i++){
            curNode = curNode.next; 
        }
        curNode.next = curNode.next.next;
    }
}

class ListNode{
    int val;
    ListNode next;

    public ListNode(int val){
        this.val = val;
    }

    public ListNode(){}
}

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */

反转链表

题目

地址:https://leetcode.cn/problems/reverse-linked-list/description/

题意:反转一个单链表。

示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL

img

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        //双指针方法
        ListNode preNode = null;
        ListNode curNode = head;
        ListNode tempNode = null;

        while(curNode != null){
          //保存下一个节点
          tempNode = curNode.next;
          curNode.next = preNode;
          preNode = curNode;
          curNode = tempNode;
        }
        return preNode;
    }
}

双指针方法是最容易理解的,当然参考代码随想录,还有其他的两种方法就是递归方法和从后向前递归方法

递归:

class Solution {
    public ListNode reverseList(ListNode head) {
        return reverse(null, head);
    }

    private ListNode reverse(ListNode prev, ListNode cur) {
        if (cur == null) {
            return prev;
        }
        ListNode temp = null;
        temp = cur.next;// 先保存下一个节点
        cur.next = prev;// 反转
        // 更新prev、cur位置
        // prev = cur;
        // cur = temp;
        return reverse(cur, temp);
    }
}

从后向前递归

class Solution {
    ListNode reverseList(ListNode head) {
        // 边缘条件判断
        if(head == null) return null;
        if (head.next == null) return head;
        
        // 递归调用,翻转第二个节点开始往后的链表
        ListNode last = reverseList(head.next);
        // 翻转头节点与第二个节点的指向
        head.next.next = head;
        // 此时的 head 节点为尾节点,next 需要指向 NULL
        head.next = null;
        return last;
    } 
}

两两交换链表中的节点

题目

地址:

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

img

思路:

使用虚拟头结点

24.两两交换链表中的节点1

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        //使用虚拟头结点来操作
        ListNode dumpNode = new ListNode(-1);
        dumpNode.next = head;
        ListNode curNode = dumpNode;
        //定义三个临时节点
        ListNode firstNode;//两个节点中的第一个节点
        ListNode secondeNode;//两个节点中的第二个节点
        ListNode temp;两个节点后面的节点

        while(curNode.next!=null && curNode.next.next != null){
            temp = curNode.next.next.next;
            firstNode = curNode.next;
            secondeNode  =curNode.next.next;
            //进行交换
            curNode.next = secondeNode;
            secondeNode.next = firstNode;
            firstNode.next = temp;
            //下一轮循环
            curNode = firstNode;
        }
        return dumpNode.next;
    }
}

删除链表倒数第N个节点

题目

地址:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/

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

img

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //使用快慢指针方法
        ListNode dumpNode = new ListNode(0);
        dumpNode.next = head;

        //定义快慢指针
        ListNode fastIndex = dumpNode;
        ListNode slowIndex = dumpNode;

        //快慢指针只要相差n即可
        for(int i=0;i<=n;i++){
            fastIndex = fastIndex.next;
        }
        while(fastIndex != null){
            fastIndex = fastIndex.next;
            slowIndex = slowIndex.next;
        }

        if(slowIndex.next != null){
            slowIndex.next = slowIndex.next.next;
        }

        return dumpNode.next;
    }
}

链表相交

题目

地址:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

img

简单来说,就是求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。

代码

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode p1 = headA;
        ListNode p2 = headB;
        while(p1 != p2){
            if(p1 == null){
                p1 = headB;
            }else{
                p1 = p1.next;
            }
            if(p2 == null){
                p2 = headA;
            }else{
                p2 = p2.next;
            }
        }
        return p1;
    }
}

环形链表II

题目

地址:https://leetcode.cn/problems/linked-list-cycle-ii/description/

题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

思路:

判断链表是否有环,可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

判断链表是否有环

可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

此时已经可以判断链表是否有环了,那么接下来要找这个环的入口了。

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:

img

那么相遇时: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。

因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:

(x + y) * 2 = x + y + n (y + z)

两边消掉一个(x+y): x + y = n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。

所以要求x ,将x单独放在左面:x = n (y + z) - y ,

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

这个公式说明什么呢?

先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。

当 n为1的时候,公式就化解为 x = z

这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。

让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。

动画如下:

142.环形链表II(求入口)

那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。

其实这种情况和n为1的时候 效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。

代码

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        //使用快慢指针来实现
        ListNode slowNode = head;
        ListNode fastNode = head;
        while(fastNode != null && fastNode.next != null){
            slowNode = slowNode.next;
            fastNode = fastNode.next.next;
            if(fastNode == slowNode){//有环
                ListNode indexNode1 = head;
                ListNode indexNode2 = slowNode;
                while(indexNode1 != indexNode2){
                    indexNode1 = indexNode1.next;
                    indexNode2 = indexNode2.next;
                }
                return indexNode1;
            }
        }
        return null;
    }
}

【ps】:所有的图片引用来自代码随想录,网址:https://programmercarl.com/

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

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

相关文章

electron-updater软件自动检测更新 +无服务器本地测试

大家好&#xff0c;我是小黄。 今天分享一下如何0基础实现electron自动检测更新功能。 一. 安装 electron-updater 实现自动更新 安装依赖 electron-updater npm install electron-updater 二. 修改package.josn "publish": {"provider": "generi…

【Linux——实现一个简易shell】

黑暗中的我们都没有说话&#xff0c;你只想回家&#xff0c;不想你回家............................................................... 文章目录 前言 一、【shell工作过程】 二、【命令行参数】 2.1、【获取命令行参数】 1、【输出命令行提示符】 2、【输入命令行参数】 2…

【超全总结】深度学习分割模型的损失函数类别及应用场景

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

新增工作台模块,任务中心支持一键重跑,MeterSphere开源持续测试工具v3.5版本发布

2024年11月28日&#xff0c;MeterSphere开源持续测试工具正式发布v3.5版本。 在这一版本中&#xff0c;MeterSphere新增工作台模块&#xff0c;工作台可以统一汇总系统数据&#xff0c;提升测试数据的可视化程度并增强对数据的分析能力&#xff0c;为管理者提供测试工作的全局…

大模型训练核心技术RLHF

本文此次的主要内容是使用强化学习训练语言模型的过程&#xff0c;特别是通过人类反馈的强化学习&#xff08;RLHF&#xff09;技术来微调大语言模型。本文先介绍了预训练模型的使用&#xff0c;然后重点介绍了RLHF的第二阶段&#xff0c;即将下游任务以特定数据集的形式交给大…

Python学习笔记之IP监控及告警

一、需求说明 作为一名运维工程师&#xff0c;监控系统必不可少。不过我们的监控系统往往都是部署在内网的&#xff0c;如果互联网出口故障&#xff0c;监控系统即使发现了问题&#xff0c;也会告警不出来&#xff0c;这个时候我们就需要补充监控措施&#xff0c;增加从外到内的…

联想YOGA Pro 14s至尊版电脑找不到独立显卡(N卡)问题,也无法安装驱动的问题

问题描述 电脑是联想YOGA Pro 14s至尊版&#xff0c;电脑上装的独立显卡是4060&#xff0c;一直是能够使用独立显卡的。然而有两次突然就找不到显卡了&#xff0c;NVIDIA CONTROL PANEL也消失了&#xff0c;而且也无法安装驱动。具体表现如下&#xff1a; 无法连接外接显示器…

【优先算法-滑动窗口——包含不超过两种字符的最长子串】

目录 1.题目解析 题目来源 测试用例 2.算法原理 1.入窗口 2.出窗口 3.更新结果 3.实战代码 代码解析 1.题目解析 题目来源 包含不超过两种字符的最长子串——牛客网 测试用例 2.算法原理 1.入窗口 这里的窗口限制条件为:窗口内不能超过两种字符&#xff0c;所以使用…

图片预处理技术介绍4——降噪

图片预处理 大家好&#xff0c;我是阿赵。   这一篇将两种基础的降噪算法。   之前介绍过均值模糊和高斯模糊。如果从降噪的角度来说&#xff0c;模糊算法也算是降噪的一类&#xff0c;所以之前介绍的两种模糊可以称呼为均值降噪和高斯降噪。不过模糊算法对原来的图像特征的…

Python蒙特卡罗MCMC:优化Metropolis-Hastings采样策略Fisher矩阵计算参数推断应用—模拟与真实数据...

全文链接&#xff1a;https://tecdat.cn/?p38397 本文介绍了其在过去几年中的最新开发成果&#xff0c;特别阐述了两种有助于提升 Metropolis - Hastings 采样性能的新要素&#xff1a;跳跃因子的自适应算法以及逆 Fisher 矩阵的计算&#xff0c;该逆 Fisher 矩阵可用作提议密…

cad软件打不开报错cad acbrandres dll加载失败

一切本来很顺利哒 但是&#xff0c;当我用快捷方式打开时&#xff0c;就出现了这个错误。进入文件路径&#xff0c;是有这个的&#xff1b; 在文件路径直接打开&#xff0c;也会提示错误 原因竟然是我改了个名字&#xff1a; 随便选的文件路径&#xff0c;空的,文件名为Acr…

HBU深度学习作业9

1. 实现SRN &#xff08;1&#xff09;使用Numpy实现SRN import numpy as npinputs np.array([[1., 1.],[1., 1.],[2., 2.]]) # 初始化输入序列 print(inputs is , inputs)state_t np.zeros(2, ) # 初始化存储器 print(state_t is , state_t)w1, w2, w3, w4, w5, w6, w7, …

泛化调用 :在没有接口的情况下进行RPC调用

什么是泛化调用&#xff1f; 在RPC调用的过程中&#xff0c;调用端向服务端发起请求&#xff0c;首先要通过动态代理&#xff0c;动态代理可以屏蔽RPC处理流程&#xff0c;使得发起远程调用就像调用本地一样。 RPC调用本质&#xff1a;调用端向服务端发送一条请求消息&#x…

纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架

前言​ 开发纯go插件的原因是因为目前 Go 生态系统中几乎所有现有的人脸检测解决方案都是纯粹绑定到一些 C/C 库&#xff0c;如 ​​OpenCV​​ 或 ​​​dlib​​​&#xff0c;但通过 ​​​cgo​​​ 调用 C 程序会引入巨大的延迟&#xff0c;并在性能方面产生显著的权衡。…

基于SpringBoot实现的编程训练系统(代码+论文)

&#x1f389;博主介绍&#xff1a;Java领域优质创作者&#xff0c;阿里云博客专家&#xff0c;计算机毕设实战导师。专注Java项目实战、毕设定制/协助 &#x1f4e2;主要服务内容&#xff1a;选题定题、开题报告、任务书、程序开发、项目定制、论文辅导 &#x1f496;精彩专栏…

【Spring】Spring IOCDI:架构旋律中的“依赖交响”与“控制华章”

前言 &#x1f31f;&#x1f31f;本期讲解关于Spring IOC&DI的详细介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么…

webpack(react)基本构建

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 Webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。它的主要功能是将各种资源&#xff08;如 JavaScript、CSS、图片等&#xff09;视为模块&#xff0c;并将它们打包成一个或多个输出文件&#xff0c;以便…

mysql--二进制安装编译安装yum安装

二进制安装 创建用户和组 [rootlocalhost ~]# groupadd -r -g 306 mysql [rootlocalhost ~]# useradd -r -g 306 -u 306 -d /data/mysql mysql 创建文件夹并添加所属文件用户和组 [rootlocalhost ~]# mkdir -p /data/mysql [rootlocalhost ~]# chown mysql:mysql /data/mysql …

DRM(数字权限管理技术)防截屏录屏----ffmpeg安装

提示&#xff1a;ffmpeg安装 文章目录 [TOC](文章目录) 前言一、下载二、配置环境变量三、运行ffmpeg四、文档总结 前言 FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的…

MongoDB集群分片安装部署手册

文章目录 一、集群规划1.1 集群安装规划1.2 端口规划1.3 目录创建 二、mongodb安装&#xff08;三台均需要操作&#xff09;2.1 下载、解压2.2 配置环境变量 三、mongodb组件配置3.1 配置config server的副本集3.1.1 config配置文件3.1.2 config server启动3.1.3 初始化config …