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

Leetcode链表问题汇总

目录

      • [2. 两数相加](https://leetcode.cn/problems/add-two-numbers/)
      • [206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/)
      • [206. 反转链表 II](https://leetcode.cn/problems/reverse-linked-list-ii/)
      • [19. 删除链表的倒数第 N 个结点](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)
      • [21. 合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/)
      • [61. 旋转链表](https://leetcode.cn/problems/rotate-list/)
      • [82. 删除排序链表中的重复元素 II](https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/)
      • [83. 删除排序链表中的重复元素重复元素](https://leetcode.cn/problems/remove-duplicates-from-sorted-list/)
      • [141. 环形链表](https://leetcode.cn/problems/linked-list-cycle/)
      • [142. 环形链表 II](https://leetcode.cn/problems/linked-list-cycle-ii/)
      • [143. 重排链表](https://leetcode.cn/problems/reorder-list/)

2. 两数相加

比较简单的题目,头结点标示的个位数字,因此直接模拟就可以了。注意链表相关的题目可以添加一个虚拟头节点,用来简化一些边界情况的处理。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* res = new ListNode(-1);ListNode* cur = res;int carry = 0; //进位标示while (l1 || l2) {int v1 = l1 ? l1 -> val : 0;int v2 = l2 ? l2 -> val : 0;int sum = v1 + v2 + carry;carry = sum / 10;cur -> next = new ListNode(sum % 10);cur = cur -> next;if (l1) l1 = l1 -> next;if (l2) l2 = l2 -> next;}if (carry) cur -> next = new ListNode(1);return res -> next;}
};

206. 反转链表

翻转即将所有节点的next指针指向前驱节点。由于是单链表,我们在迭代时不能直接找到前驱节点,所以我们需要一个额外的指针保存前驱节点。同时在改变当前节点的next指针前,不要忘记保存它的后继节点。
其实相当于头插法!

class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* prev = nullptr;ListNode* cur = head;while (cur) {ListNode* nxt = cur -> next;cur -> next = prev;prev = cur;cur = nxt;}return prev;}
};

还有一种递归的写法:
首先我们先考虑 reverseList 函数能做什么,它可以翻转一个链表,并返回新链表的头节点,也就是原链表的尾节点。
所以我们可以先递归处理 reverseList(head->next),这样我们可以将以head->next为头节点的链表翻转,并得到原链表的尾节点tail,此时head->next是新链表的尾节点,我们令它的next指针指向head,并将head->next指向空即可将整个链表翻转,且新链表的头节点是tail。

class Solution {
public:ListNode* reverseList(ListNode* head) {if (!head || !head->next) return head;ListNode *tail = reverseList(head->next);head->next->next = head;head->next = nullptr;return tail;}
};

206. 反转链表 II

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* reverseBetween(ListNode* head, int left, int right) {ListNode* dummy = new ListNode(-1); // 建立一个虚拟头节点,因为有可能left==1,避免处理边界情况dummy -> next = head;auto a = dummy;for (int i = 0; i < left - 1; i++) a = a -> next; //找到left的前一个节点auto b = a -> next, c = b -> next;//接下来是反转链表的逻辑,要做right - left次for (int i = 0; i < right - left; i++) {auto d = c -> next;c -> next = b;b = c, c = d;}//两头的指针搞正确a -> next -> next = c;a -> next = b;return dummy -> next;}
};

19. 删除链表的倒数第 N 个结点

找到前面的那个点,改掉指针即可。

class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* dummy = new ListNode(-1);dummy -> next = head;// sz: 包含虚拟头结点的整个链表的长度int sz = 0;for (auto p = dummy; p; p = p -> next) sz++;// 倒数第N个节点,也就是正数的(sz+1-n)个点.// 要删除这个点,要先到它前面的那个点,也就是第(sz-n)个点,从dummy开始跳,需要跳(sz-n-1)步auto p = dummy;for (int i = 0; i < sz - n - 1; i++) p = p -> next;p -> next = p -> next -> next;return dummy -> next;}
};

21. 合并两个有序链表

判断大小,直接模拟即可,注意代码的简洁性。

class Solution {
public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {ListNode* dummy=  new ListNode(-1);ListNode* tail = dummy;while (l1 && l2) {if (l1 -> val < l2 -> val) tail = tail -> next = l1, l1 = l1 -> next;else tail = tail -> next = l2, l2 = l2 -> next;}if (l1) tail -> next = l1;if (l2) tail -> next = l2;return dummy -> next;}
};

61. 旋转链表

相当于把后面一部分的链表拼接到前面

class Solution {
public:ListNode* rotateRight(ListNode* head, int k) {if (!head) return head;int sz = 0; //链表长度ListNode* tail; //当前链表的尾节点for (auto p = head; p; p = p -> next) {tail = p;sz++;}k %= sz;if (!k) return head;auto p = head;//找到前半部分的最后的元素for (int i = 0; i < sz - k - 1; i++) p = p -> next;//把后半部分拼到前面即可//1. 前半部分的尾结点的next指向空//2. 后半部分的尾结点的next指向链表的头结点tail -> next = head;head = p -> next; // 这个是最新的头结点p -> next = nullptr;return head;}
};

82. 删除排序链表中的重复元素 II

类似于双指针,判断一段相等值的个数是只有一个,还是至少两个,来选择不同的策略。注意看代码里的条件判断的部分。

class Solution {
public:ListNode* deleteDuplicates(ListNode* head) {auto dummy = new ListNode(-1);dummy -> next = head;auto p = dummy;while (p -> next) {auto first = p -> next;auto end = first -> next;// 让end走到和first不等的节点while (end && end -> val == first -> val) end = end -> next; // 说明相等这一段只有一个if (first -> next == end) p = p -> next;// 至少有两个,那么跳过这一段else p -> next = end;}return dummy -> next;}
};

83. 删除排序链表中的重复元素重复元素

其实把上面题的else里面改一下就可以了

class Solution {
public:ListNode* deleteDuplicates(ListNode* head) {auto dummy = new ListNode(-1);dummy -> next = head;auto p = dummy;while (p -> next) {auto first = p -> next;auto end = first -> next;while (end && end -> val == first -> val) end = end -> next; if (first -> next == end) p = p -> next;else p -> next -> next = end;}return dummy -> next;}
};

当然也有更简单的写法,思路就是判断一下枚举到的值和当前的值是否相等,只保留不相等的节点

class Solution {
public:ListNode* deleteDuplicates(ListNode* head) {if (!head) return head;auto cur = head;for (auto p = head -> next; p; p = p -> next) {if (p -> val != cur -> val) cur = cur -> next = p;}cur -> next = nullptr;return head;}
};

141. 环形链表

用两个指针从头开始扫描,第一个指针每次走一步,第二个指针每次走两步。如果走到 null,说明不存在环;否则如果两个指针相遇,则说明存在环。
原因:
假设链表存在环,则当第一个指针走到环入口时,第二个指针已经走到环上的某个位置,距离环入口还差 x 步。由于第二个指针每次比第一个指针多走一步,所以第一个指针再走 x步,两个指针就相遇了。
复杂度分析,由于慢指针走的总步数小于链表总长度,复杂度为 O ( N ) O(N) O(N).

class Solution {
public:bool hasCycle(ListNode *head) {if (!head || !head -> next) return false;ListNode* slow = head;ListNode* fast = head -> next;while (slow && fast) {if (slow == fast) return true;slow = slow -> next;fast = fast -> next;if (fast) fast = fast -> next;}return false;}
};

142. 环形链表 II

143. 重排链表

相关文章:

Leetcode链表问题汇总

目录 [2. 两数相加](https://leetcode.cn/problems/add-two-numbers/)[206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/)[206. 反转链表 II](https://leetcode.cn/problems/reverse-linked-list-ii/)[19. 删除链表的倒数第 N 个结点](https://leetcode.cn/p…...

基于卷的磁盘扫描算法设计

1、设计目的 常规情况下&#xff0c;当我们扫描计算机的硬盘时&#xff0c; 通常会使用诸如FindFirstFile/FindNextFile(Windows)&#xff0c;或者opendir/readdir(Linux)遍历扫描的目录。 一般情形下&#xff0c;由于文件数量相对较少&#xff0c;文件夹层次低&#xff0c;扫…...

计算机组成原理-存储器概念

计算机组成原理-存储器 存储系统的基本概念 1.层次结构 可以直接被CPU读取: 高速缓存:cache主存储器: 主存和内存 辅助存储器: 辅存和外存 2.分类 1.按层次结构划分 如上面所示 2.按存储介质 半导体存储器磁表面存储器光存储器 3.按信息可更改性 r/w存储器ROM(只读存储器) 4…...

力扣刷题 day54:10-24

1.十进制整数的反码 每个非负整数 N 都有其二进制表示。例如&#xff0c; 5 可以被表示为二进制 "101"&#xff0c;11 可以用二进制 "1011" 表示&#xff0c;依此类推。注意&#xff0c;除 N 0 外&#xff0c;任何二进制表示中都不含前导零。 二进制的反…...

Java基础篇 | Java8流式编程

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…...

SolidworksSimulation完成对压力容器的强度分析

如何通过使用SolidworksSimulation完成对压力容器的分析并查看实 体的膜片应力强度以及弯曲应力强度&#xff0c;操作简单易学&#xff0c;让我们进入到操作界面。 我们以罐体底部实体模型为例&#xff0c;这里已经提前设置好了材料。 点击新算例&#xff0c;选择静应力分析 由…...

【C++】继承 ⑨ ( 继承中成员变量同名的处理方案 )

文章目录 一、继承中成员变量同名的处理方案1、继承中成员变量同名的场景说明2、使用域作用符区分同名成员变量 二、代码示例 - 继承中成员变量同名的处理方案 一、继承中成员变量同名的处理方案 1、继承中成员变量同名的场景说明 子类 继承 父类 的 成员 , 如果 子类 中定义了…...

Python报错:‘EagerTensor‘ object has no attribute ‘reshape‘

在使用RPython时&#xff0c;发现python代码部分报错&#xff1a;‘EagerTensor‘ object has no attribute ‘reshape‘ 如何解决&#xff1f; 使用np.array 转换为array&#xff0c;再进行reshape 参考&#xff1a; ‘EagerTensor‘ object has no attribute ‘reshape‘处…...

docker-compose手册

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 前言 一些自己经常用到的docker-compose知识。 一、运行和启动项目 1.1、docker-compose运行…...

【珠峰 WEB 前端架构师课程】学习笔记 100 篇(完结)

该课程是珠峰姜文老师讲的&#xff0c;个人觉得讲的很不错&#xff0c;一路在 b 站学习下来做了 100 篇的学习笔记&#xff0c;收获颇丰。 该课程主要讲了高阶函数、函数柯里化、发布订阅模式、观察者模式、从 0 到 1 实现一个 promise&#xff0c;co 库的实现、eventloop 执行…...

Java线程中sleep()、wait()、yield()、join()方法的使用

1.sleep() sleep(): sleep 方法属于 Thread 类&#xff0c;该行为中线程不会释放锁&#xff0c;只阻塞线程&#xff0c;让出cpu给其他线程&#xff0c;当达到指定的时间后会自动恢复运行状态继续运行。 2.wait() wait(): 该方法属于 Object 类&#xff0c;在这个过程里线程会…...

【机器学习】数据均衡学习笔记

文章目录 序言1. 样本不均衡2. 样本不均衡的影响以及样本均衡的意义3. 什么时候需要进行样本均衡/数据均衡4. 数据不均衡的解决办法 序言 数据集制作过程中需要关注样本均衡问题&#xff0c;学习笔记&#xff0c;简单记录 1. 样本不均衡 分类任务中不同类别样本数差别很大的…...

【软件教程】如何用C++交叉编译出能在Android运行的ELF程序或so动态库

一、配置NDK交叉编译平台 1. 打开Android的官方ndk下载链接https://developer.android.com/ndk/downloads?hlzh-cn&#xff0c;下载windows 64位ndk环境包。 2. 解压后将具有以下文件的路径加入到系统环境变量。 3. 配置好环境变量&#xff0c;如下图所示&#xff0c;Path中存…...

进阶JAVA篇- Map 系列集合的遍历方法与常用API

目录 1.0 Map 集合的说明 1.1 Map 集合的常用方法 1.2 Map 系列集合的特点 2.0 Map 系列集合的遍历方法&#xff08;三种方法&#xff09; 2.1 使用 keySet() 方法遍历 2.2 使用 entrySet() 方法遍历 2.3 使用 forEach() 方法遍历&#xff08;Java 8&#xff09; 1.0 Map 集合的…...

Auth.js:多合一身份验证解决方案 | 开源日报 No.60

nodejs/node Stars: 96.2k License: NOASSERTION Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。它具有以下关键特性和核心优势&#xff1a; 强大&#xff1a;Node.js 提供了强大且高效的服务器端运行能力&#xff0c;可以处理并发请求&#xff0c;并支持异步编程…...

SpringBoot整合Activiti7——任务监听器(七)

文章目录 一、任务监听器事件类型配置方式(选)代码实现xml文件创建监听器class方式expression方式delegateExpression 测试流程部署流程启动流程完成任务 一、任务监听器 任务监听器可以在任务创建、任务分配、任务完成、任务删除发生时触发&#xff0c;从而执行相应的逻辑。 事…...

电解电容寿命与哪些因素有关?

电解电容在各类电源及电子产品中是不可替代的元器件&#xff0c;这些电子产品中由于应用环境的原因&#xff0c;使它成为最脆弱的一环&#xff0c;所以&#xff0c;电解电容的寿命也直接影响了电子产品的使用寿命。 一、电解电容失效模式与因素概述 铝电解电容器正极、负极引出…...

Opencv-图像插值与LUT查找表

图像像素的比较 白色是255&#xff0c;黑色是0 min(InputArray src1,InputArray src2,OutputArray dst) max(InputArray src1,InputArray src2,OutpurArray dstsrc1:第一个图像矩阵&#xff0c;通道数任意src2&#xff1a;第二个图像矩阵&#xff0c;尺寸和通道数以及数据类型…...

我为什么写博客?写博客给我带来了什么?

1、写博客的契机 &#xff08;1&#xff09;刚开始接触CSDN&#xff0c;是大三的时候开始学习嵌入式开发&#xff0c;经常需要到网上百度查资料&#xff0c;由此经常游览CSDN上的博客&#xff1b; &#xff08;2&#xff09;在嵌入式的过程中&#xff0c;需要总结学习过的知识。…...

jdk11的HttpClient

我们都知道在jdk11之前都在用okhttp或者org.apache.httpcomponents 其实早在jdk9的时候这个方案就在孵化中 上面的截图来自openjdk的官网&#xff0c;注&#xff1a;openjdk是个开源项目&#xff0c;不存在侵权现象 这是openjdk的官网&#xff1a;JEP 110: HTTP/2 Client (In…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道

文/法律实务观察组 在债务重组领域&#xff0c;专业机构的核心价值不仅在于减轻债务数字&#xff0c;更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明&#xff0c;合法债务优化需同步实现三重平衡&#xff1a; 法律刚性&#xff08;债…...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...