当前位置: 首页 > news >正文

《 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.dtcms.com/a/304589.html

相关文章:

  • 【LeetCode】大厂面试算法真题回忆(111)--身高排序
  • 鱼皮项目简易版 RPC 框架开发(五)
  • 2.oracle保姆级安装教程
  • 逐渐走进Ai世界~
  • Django模型开发:模型字段、元数据与继承全方位讲解
  • Unity_SRP Batcher
  • 【WRF-Chem 实例1】namelist.input 详解- 模拟CO2
  • 基于AI代码疫苗技术的开源软件供应链安全治理
  • C# _列表(List<T>)_ 字典(Dictionary<TKey, TValue>)
  • 【dropdown组件填坑指南】—怎么实现下拉框的位置计算
  • 【机器学习深度学习】为什么需要分布式训练?
  • 从硬编码到自主智能体:营销AI的20年技术演进与未来展望
  • 前端开发为什么没有后端开发那么清除业务
  • sqLite 数据库 (2):
  • 摔倒识别误报率↓79%:陌讯动态时序融合算法实战解析
  • System V IPC机制:进程通信的统一设计
  • 单片机(STM32-WIFI模块)
  • 【JavaScript】手写 Object.prototype.toString()
  • Qt 移动应用常见问题与解决方案
  • React服务端渲染 Next 使用详解
  • 安卓模拟器 adb Frida hook 抓包
  • Ubuntu第一步——下载、网络、apt
  • 用系统架构思维,告别“意大利面条式”系统提示词
  • 艾利特机器人:光伏机器人如何重塑清洁能源制造新格局
  • 极光GPTBots亮相WAIC,并发布全新Multi-Agent平台
  • AUTOSAR Mcal Gpt - 模块介绍
  • 能源高效利用如何实现?楼宇自控系统智能化监管建筑设备
  • 电池充放电测试仪:解锁能源存储性能的关键工具|鑫达能
  • 【LeetCode 热题 100】34. 在排序数组中查找元素的第一个和最后一个位置——二分查找
  • 文件操作与IO流