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

【算法】链表

  零:链表常用技巧

1:引入虚拟头结点

(1)便于处理边界情况

(2)方便我们对链表操作

2:两步尾插,头插 

(1)尾插

tail指向最后一个节点,tail.next 指向新尾节点,tail指针在指向新尾节点

(2)头插

新头结点.next = 虚拟头节点newhead.next

虚拟头节点newhead.next = 新头结点.

3:插入节点 

若有一个指针(next)指向被插入节点后的那个节点,那么这四句代码的顺序随意

反之,前两句必须写在前面(这两句顺序可以互换),后两句必须写在后面

一: 两数相加

2. 两数相加

/*** 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 addTwoNumbers(ListNode l1, ListNode l2) {//先new一个虚拟节点ListNode newHead = new ListNode(0);ListNode cur1 = l1 , cur2 = l2, cur3 = newHead;int t = 0;while(cur1 != null || cur2 != null || t != 0){//对第一个链表做加法if(cur1 != null){t += cur1.val;cur1 = cur1.next;}//对第二个链表做加法if(cur2 != null){t += cur2.val;cur2 = cur2.next;}//移动cur3.next = new ListNode(t%10);cur3 = cur3.next;t = t/10;}return newHead.next;}
}

二:两两交换链表中的节点

两两交换链表中的节点

/*** 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) {if (head == null || head.next == null) {return head;}// 虚拟头结点ListNode newHead = new ListNode(0);newHead.next = head;// 先搞四个指针ListNode prev = newHead, cur = prev.next, next = cur.next, nnext = next.next;while (cur != null && next != null) {prev.next = next;next.next = cur;cur.next = nnext;prev = cur;cur = nnext;if (cur != null) {next = cur.next;}if (next != null) {nnext = next.next;}}return newHead.next;}
}

三:143. 重排链表(写的酣畅淋漓的一道题 )

这道题涵盖了双指针,前插,尾插,合并两个链表,代码调试也很爽,很重要的是我们在变量的选择和名称定义上一定要规范,否则写代码就是一种折磨

 

/*** 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 void reorderList(ListNode head) {if(head == null || head.next == null || head.next.next == null) return ;// 1:找中间节点ListNode fast = head;ListNode slow = head;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}// 逆序准备工作:新的头结点ListNode head1 = head;ListNode head2 = new ListNode(0);ListNode cur = slow.next;slow.next = null;// 将上半段尾插null,分开标志// 2:逆序头插(很明显头插一直要用到的指针是头结点,这是关键),这里逆序链表头结点是虚拟节点注意注意!!!!while (cur != null) {ListNode tmp = cur.next;cur.next = head2.next;head2.next = cur;// cur = cur.next;错的cur更新为tmp,cur.next已经指向null了cur = tmp;}// 3:合并两个链表(尾插)双指针ListNode ret = new ListNode(0);ListNode prev = ret;ListNode cur1 = head1, cur2 = head2.next;while (cur1 != null) {// 左半链表长度>=右半// 先插左prev.next = cur1;cur1 = cur1.next;prev = prev.next;//  在插右if (cur2 != null) {prev.next = cur2;cur2 = cur2.next;prev = prev.next;}}}
}

四:合并K个升序链表

 23. 合并 K 个升序链表

这道题的解法有三种,暴力解法(超时),优先级队列(文章写法),递归(难)

复习了优先级队列的lambda表达式写法,爽,战斗爽!AC爽

/*** 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 mergeKLists(ListNode[] lists) {PriorityQueue<ListNode> queue = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);// 小根堆// 放入第一批头结点for (ListNode head : lists) {if (head != null) {queue.offer(head);}}// 合并链表ListNode ret = new ListNode(0);ListNode cur = ret;// 定义指针while (!queue.isEmpty()) {ListNode tmp = queue.poll();cur.next = tmp;cur = cur.next;if (tmp.next != null) {tmp = tmp.next;queue.offer(tmp);}}return ret.next;}
}

五:K个一组翻转链表

25. K 个一组翻转链表

/*** 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 reverseKGroup(ListNode head, int k) {// 第一步计算需要逆序多少组 int n = 0;ListNode cur = head;while(cur != null){n++;cur = cur.next;}n = n/k;//逆序组数ListNode tmp = head;ListNode ret = new ListNode(0);ListNode prev = ret;while(n != 0){ListNode move = tmp;int m = k;while(m != 0){//执行k次头插法ListNode next = tmp.next;tmp.next = prev.next;prev.next = tmp;tmp = next;m--;}prev = move;n--;}prev.next = tmp;return ret.next;}
}

六:相交链表

力扣k神的图解,真的nb,太清晰了

/*** 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 A = headA, B = headB;while (A != B) {A = A != null ? A.next : headB;B = B != null ? B.next : headA;}return A;}
}

七:回文链表

心得:

1:尽量画图

2:确定中间节点的时候,奇数个节点好理解,偶数个节点指向的是右边那个节点

3:反转链表后原链表并没有断开

4:反转链表有两种方法,第一种搞一个虚拟头结点,进行头插,第二种递归。战斗爽!塔塔开

/*** 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 boolean isPalindrome(ListNode head) {ListNode mid = midNode(head);ListNode reverseHead = reverseList2(mid);//没有断while(reverseHead != null){if(head.val != reverseHead.val){return false;}head = head.next;reverseHead = reverseHead.next;}return true;}public ListNode midNode(ListNode head){//快慢双指针ListNode slow = head;ListNode fast = head;while(fast != null && fast.next != null){slow = slow.next;fast = fast.next.next;}return slow;}public ListNode reverseList(ListNode head){//new 虚拟null节点ListNode pre = null;ListNode cur = head;//头插while(cur != null){ListNode tmp = cur.next;cur.next = pre;pre = cur;cur = tmp;}return pre;}public ListNode reverseList2(ListNode head){//递归的方法,head等不等于null,就是以防给的是空链表if(head == null || head.next == null){return head;}ListNode newHead = reverseList(head.next);//新的头结点head.next.next = head;head.next = null;return newHead;}}

相关文章:

【算法】链表

零&#xff1a;链表常用技巧 1&#xff1a;引入虚拟头结点 &#xff08;1&#xff09;便于处理边界情况 &#xff08;2&#xff09;方便我们对链表操作 2&#xff1a;两步尾插&#xff0c;头插 &#xff08;1&#xff09;尾插 tail指向最后一个节点&#xff0c;tail.next…...

集成测试总结文档

1. 集成测试的定义 集成测试&#xff08;Integration Testing&#xff09;是在单元测试之后&#xff0c;将多个独立的软件模块或组件组合在一起进行测试的过程&#xff0c;目的是验证这些模块之间的接口、数据传递、协作逻辑是否符合设计要求&#xff0c;并发现因集成引发的缺…...

关于Dest1ny:我的创作纪念日

Dest1ny 因为这是csdn任务&#xff0c;我就稍微“写”了一下&#xff01; 如果大家真的有什么想聊的或者想一起学习的&#xff0c;欢迎在评论区或者私信中与我讨论&#xff01; 2025想说的话 我就把我想说的写在前面&#xff01; 不用对未来焦虑&#xff0c;不要觉得自己走…...

Python爬虫-猫眼电影的影院数据

前言 本文是该专栏的第46篇,后面会持续分享python爬虫干货知识,记得关注。 本文笔者以猫眼电影为例子,获取猫眼的影院相关数据。 废话不多说,具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。接下来,跟着笔者直接往下看正文详细内容。(附带完整代码) …...

【计算机网络】传输层数据段格式

在计算机网络中&#xff0c;数据段&#xff08;Segment&#xff09; 是传输层协议&#xff08;如 TCP 或 UDP&#xff09;使用的数据单元。TCP 和 UDP 的数据段格式有所不同&#xff0c;以下是它们的详细说明&#xff1a; 1. TCP 数据段格式 TCP&#xff08;传输控制协议&…...

nsc account 及user管理

从安全角度&#xff0c;推荐使用sign 模式进行nats account及用户管理 把权限放到account level 用户密码泄露可以通过快速更换用户可以设置过期日期&#xff0c;进行安全轮换 此外通过nsc 管理用户和权限&#xff0c;可以统一实现全局管控&#xff0c;包括subject管控&#…...

晶闸管主要参数分析与损耗计算

1. 主要参数 断态正向可重复峰值电压 :是晶闸管在不损坏的情况下能够承受的正向最大阻断电压。断态正向不可重复峰值电压 :是晶闸管只有一次可以超过的正向最大阻断电压,一旦晶闸管超过此值就会损坏,一般情况下 反向可重复峰值电压 :是指晶闸管在不损坏的情况下能够承受的…...

.net6 mvc 获取网站(服务器端)的IP地址和端口号

注意&#xff1a;是网站的&#xff0c;服务端的 IP地址&#xff0c; 不是当前用户电脑的、本地的IP地址 两个图&#xff1a; 分析&#xff1a; var AbsolutePath HttpContext.Request.Url.AbsolutePath;//"/Meeting/GetLastMeetingOL"var AbsoluteUri HttpContext.…...

坐井说天阔---DeepSeek-R1

前言 DeepSeek-R1这么火&#xff0c;虽然网上很多介绍和解读&#xff0c;但听人家的总不如自己去看看原论文。于是花了大概一周的时间&#xff0c;下班后有进入了研究生的状态---读论文。 DeepSeek这次的目标是探索在没有任何监督数据的情况下训练具有推理能力的大模型&#…...

数据结构与算法——快速排序

快速排序 一、核心原理&#xff1a;分治策略 1、选一个基准元素&#xff0c; 2、两个指针往中间遍历&#xff0c;比基准值小的移到一边&#xff0c;比基准值大的移到另一边&#xff0c; 一轮遍历后&#xff0c;指针相交位置就是基准值应该放置的位置&#xff0c;同时数组也…...

Node.js技术原理分析系列——Node.js调试能力分析

本文由体验技术团队屈金雄原创。 Node.js 是一个开源的、跨平台的 JavaScript 运行时环境&#xff0c;它允许开发者在服务器端运行 JavaScript 代码。Node.js 是基于 Chrome V8引擎构建的&#xff0c;专为高性能、高并发的网络应用而设计&#xff0c;广泛应用于构建服务器端应…...

在Mac arm架构终端中运行 corepack enable yarn 命令,安装yarn

文章目录 1. 什么是 Corepack&#xff1f;2. 运行 corepack enable yarn 的作用3. 如何运行 corepack enable yarn4. 可能遇到的问题及解决方法问题 1&#xff1a;corepack 命令未找到问题 2&#xff1a;Yarn 未正确安装问题 3&#xff1a;权限问题 5. 验证 Yarn 是否启用成功6…...

蓝桥杯试题:计数问题

一、题目描述 试计算在区间 1 到 n的所有整数中&#xff0c;数字 x&#xff08;0≤x≤9&#xff09;x&#xff08;0≤x≤9&#xff09; 共出现了多少次&#xff1f; 例如&#xff0c;在 1 到 11 中&#xff0c;即在 1、2、3、4、5、6、7、8、9、10、11 中&#xff0c;数字 1 …...

数学建模与MATLAB实现:数据拟合全解析

引言 数据拟合是数学建模与实验分析中的核心任务&#xff0c;旨在通过数学模型逼近实际观测数据&#xff0c;揭示变量间的潜在规律。本文基于最小二乘法的理论框架&#xff0c;结合MATLAB代码实战&#xff0c;系统讲解线性拟合、非线性拟合的实现方法&#xff0c;并通过电阻温…...

C语言——排序(冒泡,选择,插入)

基本概念 排序是对数据进行处理的常见操作&#xff0c;即将数据按某字段规律排列。字段是数据节点的一个属性&#xff0c;比如学生信息中的学号、分数等&#xff0c;可针对这些字段进行排序。同时&#xff0c;排序算法有稳定性之分&#xff0c;若两个待排序字段一致的数据在排序…...

git如何下载指定版本

要使用Git下载指定版本&#xff0c;可以通过以下步骤进行操作‌&#xff1a; ‌1. 使用Git命令行下载指定版本‌&#xff1a; 1.1 首先&#xff0c;使用git clone命令克隆整个git库到本地。例如&#xff1a;git clone [库的URL]。这将下载最新的代码到本地。‌ 1.2 进入克隆…...

数字电路-基础逻辑门实验

基础逻辑门是数字电路设计的核心元件&#xff0c;它们执行的是基本的逻辑运算。通过这些基本运算&#xff0c;可以构建出更为复杂的逻辑功能。常见的基础逻辑门包括与门&#xff08;AND&#xff09;、或门&#xff08;OR&#xff09;、非门&#xff08;NOT&#xff09;、异或门…...

新数据结构(9)——Java异常体系

异常的种类 程序本身通常无法主动捕获并处理错误&#xff08;Error&#xff09;&#xff0c;因为这些错误通常表示系统级的严重问题&#xff0c;但程序可以捕获并处理异常&#xff08;Excrption&#xff09;&#xff0c;而Error则被视为一种程序无法或不应尝试恢复的异常类型。…...

每日十题八股-补充材料-2025年2月15日

1.TCP是如何保证消息的顺序和可靠的&#xff1f; 写得超级好的文章 首先肯定是三次握手和四次挥手保证里通讯双方建立了正确有效的连接。 其次是校验和、序列号&#xff0c;ACK消息应答机制还有重传机制&#xff0c;保证了消息顺序和可靠。 同时配合拥塞机制和流量控制机制&am…...

使用 Python 爬虫获取微店快递费用 item_fee API 接口数据

在电商运营中&#xff0c;快递费用是影响商家利润和用户体验的重要因素之一。微店作为国内知名的电商平台&#xff0c;提供了丰富的 API 接口供开发者使用&#xff0c;其中也包括查询商品快递费用的接口。通过调用微店的 item_fee 接口&#xff0c;开发者可以获取指定商品的快递…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...