《 java 随想录》| LeetCode链表高频考题

前言:这是专门针对java语言讲解的算法解析(题目顺序大致参考《代码随想录》)

思维导图

操作链表

删除节点

链表-删除节点

删除链表中 D 节点时,只需将其前驱节点 C 的 next 指针指向 D 的下一个节点 E

添加节点

链表-添加节点

先让 新节点 F 的 next 指针 指向 C 原来的后继节点 D(保存原有连接,避免链表断裂);

再让 C 节点的 next 指针 指向 新节点 F,完成插入。

链表基础代码

public class ListNode {// 结点的值int val;// 下一个结点ListNode next;// 节点的构造函数(无参)public ListNode() {}// 节点的构造函数(有一个参数)public ListNode(int val) {this.val = val;}// 节点的构造函数(有两个参数)public ListNode(int val, ListNode next) {this.val = val;this.next = next;}
}

LeetCode203. 移除链表元素


一、核心逻辑:通过虚拟头节点统一移除逻辑

链表中每个节点包含值和指向下一节点的引用,要移除值为目标值的节点,可引入虚拟头节点(不存储实际数据),使其作为原头节点的前驱。这样无论是头节点还是中间节点,都能通过 “前驱节点指针调整” 的方式统一处理,避免头节点特殊处理的繁琐。

二、关键细节:虚拟头节点的使用与指针遍历

移除链表元素的难点在于头节点与其他节点处理逻辑不一致,而虚拟头节点可消除这种差异。通过维护一个遍历指针,始终指向当前待检查节点的前驱,就能统一执行 “跳过目标节点” 的操作。

解法:虚拟头节点 + 前驱指针遍历

区间(逻辑范围)含义:以虚拟头节点为起点,遍历指针 prev 始终指向当前处理节点的前驱,待检查范围是 prev.next 及之后的节点。
循环条件:while (prev.next != null)
因为只要 prev 的下一个节点存在,就需要检查其是否为目标值,循环继续。
指针调整:

  • 若 prev.next.val == val:说明下一个节点是目标节点,需移除,因此将 prev.next 指向 prev.next.next(跳过目标节点)。
  • 若 prev.next.val != val:说明下一个节点无需移除,prev 后移一位(prev = prev.next),继续检查后续节点。
    返回结果:循环结束后,所有目标节点已被移除,返回虚拟头节点的下一个节点(即新的头节点)

代码示例:

public ListNode removeElements(ListNode head, int val) {while(head!=null && head.val==val) {head = head.next;}ListNode curr = head;while(curr!=null && curr.next !=null) {if(curr.next.val == val){curr.next = curr.next.next;} else {curr = curr.next;}}return head;
}

LeetCode206. 反转链表


如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费

其实只需改变链表的next指针的指向直接将链表反转 ,而非重新定义一个新的链表,如图:

206_反转链表

我们拿有示例中的链表来举例,如动画所示

  • 初始化指针:cur 指向头节点,pre 初始化为 null,tmp 用于临时保存节点。
  • 当 cur 不为 null 时,执行以下操作:
  • 保存下一个节点:用 tmp 存储 cur 的 next 节点(避免后续指向改变后丢失)。
  • 反转当前节点指向:将 cur 的 next 指向 pre。
  • 移动指针:pre 移至 cur 位置,cur 移至 tmp 位置(即之前保存的下一个节点)。
  • 结果处理:循环结束后,pre 指向反转后链表的新头节点,返回 pre。

代码实现:

// 双指针
class Solution {public ListNode reverseList(ListNode head) {ListNode prev = null;ListNode cur = head;ListNode temp = null;while (cur != null) {temp = cur.next;// 保存下一个节点cur.next = prev;prev = cur;cur = temp;}return prev;}

LeetCode24. 两两交换链表中的节点


这道题目正常模拟就可以了。

建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。

接下来就是交换相邻两个元素了,此时一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序

初始时,cur指向虚拟头结点,然后进行如下三步:

操作之后,链表如下:

看这个可能就更直观一些了:

代码实现:

public ListNode swapPairs(ListNode head) {ListNode dummy = new ListNode(0, head);ListNode cur = dummy;while (cur.next != null && cur.next.next != null) {ListNode node1 = cur.next;// 第 1 个节点ListNode node2 = cur.next.next;// 第 2 个节点cur.next = node2; // 步骤 1node1.next = node2.next;// 步骤 3node2.next = node1;// 步骤 2cur = cur.next.next;}return dummy.next;
}

LeetCode19. 删除倒数第n个节点


双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

分为如下几步:

  • 定义fast指针和slow指针,初始值为虚拟头结点,如图:

  • fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图: 

  • fast和slow同时移动,直到fast指向末尾,如题: 

  • 删除slow指向的下一个节点,如图: 

代码实现:

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {//新建一个虚拟头节点指向headListNode dummyNode = new ListNode(0);dummyNode.next = head;//快慢指针指向虚拟头节点ListNode fastIndex = dummyNode;ListNode slowIndex = dummyNode;// 只要快慢指针相差 n 个结点即可for (int i = 0; i <= n; i++) {fastIndex = fastIndex.next;}while (fastIndex != null) {fastIndex = fastIndex.next;slowIndex = slowIndex.next;}// 此时 slowIndex 的位置就是待删除元素的前一个位置。// 具体情况可自己画一个链表长度为 3 的图来模拟代码来理解// 检查 slowIndex.next 是否为 null,以避免空指针异常if (slowIndex.next != null) {slowIndex.next = slowIndex.next.next;}return dummyNode.next;}
}

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

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

相关文章

学习嵌入式的第三十一天-数据结构-(2025.7.23)网络协议封装

今天的内容主要是网络协议以及常用工具的介绍。协议头与数据封包/拆包数据封包示例&#xff1a;MAC|IP|TCP|hello| ———————————— IP数据报IP头信息默认20字节常用网络测试工具telnetnetstatpingarpwiresharktcpdumpssh2secure crt工具安装命令sudo ufw disable sud…

STL学习(十、常用排序、拷贝、替换算法)

目录 一、常用排序算法 1.sort (1) 内置数据类型 (2)自定义数据类型 2. random_shuffle(iterator beg, iterator end) 3.merge 4.reverse 二、常用的拷贝和替换算法 1.copy(起始不如直接赋值) 2.replace 3.replace_if 4.swap 一、常用排序算法 1.sort 函数原型 s…

【Datawhale AI夏令营】科大讯飞AI大赛(大模型技术)/夏令营:让AI理解列车排期表(Task3)

我没招了jpgimport pandas as pd import requests import re import json from tqdm import tqdm from datetime import datetime, timedeltadef calculate_stop_duration(arrival_time_str, departure_time_str):"""计算列车停留时长&#xff0c;处理跨天和异常…

【前后端】node mock.js+json-server

JSON-Server 一个在前端本地运行&#xff0c;可以存储json数据的server。前端开发可以模拟服务端接口数据&#xff0c;在本地搭建一个JSON服务&#xff0c;自己产生测试数据。 使用npm全局安装json-server &#xff1a;npm install -g json-server可以通过查看版本号&#xff0…

疏老师-python训练营-Day30模块和库的导入

浙大疏锦行 知识点回顾&#xff1a; 导入官方库的三种手段导入自定义库/模块的方式导入库/模块的核心逻辑&#xff1a;找到根目录&#xff08;python解释器的目录和终端的目录不一致&#xff09; 作业&#xff1a;自己新建几个不同路径文件尝试下如何导入 一.学习知识点 DAY30 …

神经网络知识讨论

AI 核心任务与数据类型&#xff1a;特征提取核心&#xff1a;AI 的核心是从原始输入数据中提取特征&#xff0c;CV 是将图像数据转换为计算机可识别的特征&#xff0c;NLP 是将文本数据转换为特征&#xff0c;数据挖掘是将结构化数据转换为特征。数据类型特点&#xff1a;图像数…

kotlin类型可为空,进行空安全的区别

定义一个可为空的变量b(String?),默认没有&#xff1f;是不可以为空的 var b: String? "Kotlin" b null print(b) // 输出 null默认不可为空 var a: String "Kotlin" a null // 编译器报错&#xff0c;null 不能被赋给不为空的变量空安全调用&#x…

Mysql事务基础

事务是一个不可分割的数据库操作序列&#xff0c;也是数据库并发控制的基本单位&#xff0c;其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。事务是逻辑上的一组操作&#xff0c;要么都执行&#xff0c;要么都不执行 事务的特点 A&#xff08;Atomicity&#…

FastAPI入门:安装、Pydantic、并发和并行

本系列参考FastAPI官方文档&#xff1a;https://fastapi.tiangolo.com/zh/python-types/安装 使用pip安装&#xff1a; pip install fastapi此外还需要 ASGI 服务器&#xff0c;生产环境可以使用 Uvicorn 或者 Hypercorn。 ASGI服务器&#xff1a;异步服务网关接口&#xff0c;…

欢乐的周末 - 华为OD统一考试(JavaScript 题解)

题目描述 小华和小为是很要好的朋友,他们约定周末一起吃饭。 通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚餐地点不可达)。 求小华和小为都能到达的聚餐地点有多少个? 输入描述 第一行输入m和n,m代表地图的长度,n代表地图的宽度 第二行…

算法竞赛阶段二-数据结构(38)数据结构动态链表list

动态链表&#xff08;List&#xff09;的基本概念动态链表是一种线性数据结构&#xff0c;通过节点间的指针连接实现动态内存分配。与数组不同&#xff0c;链表的大小可随需增减&#xff0c;插入和删除操作的时间复杂度为 O(1)&#xff08;已知位置时&#xff09;&#xff0c;但…

Qt 移动应用推送通知实现

推送通知是移动应用提升用户粘性的核心功能——无论是即时消息提醒、活动推送还是状态更新&#xff0c;都需要通过推送功能触达用户。Qt虽未直接提供跨平台推送API&#xff0c;但可通过集成原生服务&#xff08;如Firebase Cloud Messaging、Apple Push Notification service&a…

Word和WPS文字如何制作分栏试卷?想分几栏分几栏

使用Word和WPS文字制作试卷的时候&#xff0c;通常会使用A3大小的纸张&#xff0c;横向布局。但是如果题目的题干、问题、选项文字太少&#xff0c;会带来试卷上有较大的空白&#xff0c;既不美观又浪费纸&#xff0c;解决办法就是将试卷分栏&#xff0c;根据需要分成多栏&…

ubuntu 安装vmware tools

VMware Workstation菜单栏->虚拟机->安装VMware Tools 打开ubuntu内加载的光盘&#xff0c;复制VMwareTools-10.3.26-22085142.tar.gz&#xff0c;解压出来 sudo ./vmware-install.pl #执行安装软件 VMware Tools 安装完成以后重启Ubuntu&#xff0c;重启以后就可以直…

【实时Linux实战系列】在实时应用中进行负载均衡

在实时应用中&#xff0c;负载均衡是确保系统能够高效处理多个任务的关键技术。通过合理调度任务到不同的处理单元&#xff0c;负载均衡可以提高系统的整体性能&#xff0c;减少延迟&#xff0c;并提高资源利用率。在实时 Linux 系统中&#xff0c;负载均衡尤为重要&#xff0c…

bash的特性-命令和文件自动补全

一、前言在 Linux Shell 编程和日常使用中&#xff0c;Bash 的自动补全功能 是一个非常强大且实用的特性。它不仅可以节省输入时间&#xff0c;还能有效减少拼写错误&#xff0c;提升命令执行效率。本文将带你全面了解 Bash 的自动补全机制&#xff0c;包括&#xff1a;✅ 命令…

Ubuntu系统 系统盘和数据盘扩容具体操作

Linux磁盘配置和需求&#xff0c;以下是完整的操作方案&#xff1a; 可以看到系统盘vda3 还有48GB 数据盘则是还有512GB没有挂载使用&#xff0c;下面是完成数据扩容的具体操作 一、完成系统盘扩容&#xff08;使用98GB空间&#xff09; # 1. 扩展逻辑卷&#xff08;LVM架构&am…

从0到1学Pandas(七):Pandas 在机器学习中的应用

目录一、数据预处理1.1 特征提取1.2 数据标准化与归一化1.3 特征编码二、特征工程2.1 特征选择​2.2 特征组合与衍生​2.3 缺失值处理策略​三、模型训练与评估3.1 数据集划分3.2 模型训练与预测3.3 模型评估与调优四、Pipeline 构建4.1 自动化工作流4.2 模型部署与应用4.3 模型…

LangChain和LangGraph 里面的 `create_react_agent`有什么不同

这两个函数虽然名称相同&#xff0c;但来自不同的库&#xff08;LangChain 和 LangGraph&#xff09;&#xff0c;它们在实现和使用上有一些关键区别&#xff1a; 主要区别特性LangChain 的 create_react_agentLangGraph 的 create_react_agent所属库LangChainLangGraph设计目的…

PostgreSQL 与 Oracle 数据库字段类型的详细对比

一、数值类型对比数据类型OraclePostgreSQL说明整数NUMBER(p,0)SMALLINT/INT/BIGINTOracle 统一用 NUMBER&#xff0c;PG 区分精度范围浮点数BINARY_FLOATREAL单精度浮点双精度浮点BINARY_DOUBLEDOUBLE PRECISION双精度浮点高精度小数NUMBER(p,s)NUMERIC(p,s)精确数值存储自增序…