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、设计目的 常规情况下,当我们扫描计算机的硬盘时, 通常会使用诸如FindFirstFile/FindNextFile(Windows),或者opendir/readdir(Linux)遍历扫描的目录。 一般情形下,由于文件数量相对较少,文件夹层次低,扫…...
计算机组成原理-存储器概念
计算机组成原理-存储器 存储系统的基本概念 1.层次结构 可以直接被CPU读取: 高速缓存:cache主存储器: 主存和内存 辅助存储器: 辅存和外存 2.分类 1.按层次结构划分 如上面所示 2.按存储介质 半导体存储器磁表面存储器光存储器 3.按信息可更改性 r/w存储器ROM(只读存储器) 4…...
力扣刷题 day54:10-24
1.十进制整数的反码 每个非负整数 N 都有其二进制表示。例如, 5 可以被表示为二进制 "101",11 可以用二进制 "1011" 表示,依此类推。注意,除 N 0 外,任何二进制表示中都不含前导零。 二进制的反…...
Java基础篇 | Java8流式编程
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: Java从入门到精通 ✨特色专栏…...
SolidworksSimulation完成对压力容器的强度分析
如何通过使用SolidworksSimulation完成对压力容器的分析并查看实 体的膜片应力强度以及弯曲应力强度,操作简单易学,让我们进入到操作界面。 我们以罐体底部实体模型为例,这里已经提前设置好了材料。 点击新算例,选择静应力分析 由…...
【C++】继承 ⑨ ( 继承中成员变量同名的处理方案 )
文章目录 一、继承中成员变量同名的处理方案1、继承中成员变量同名的场景说明2、使用域作用符区分同名成员变量 二、代码示例 - 继承中成员变量同名的处理方案 一、继承中成员变量同名的处理方案 1、继承中成员变量同名的场景说明 子类 继承 父类 的 成员 , 如果 子类 中定义了…...
Python报错:‘EagerTensor‘ object has no attribute ‘reshape‘
在使用RPython时,发现python代码部分报错:‘EagerTensor‘ object has no attribute ‘reshape‘ 如何解决? 使用np.array 转换为array,再进行reshape 参考: ‘EagerTensor‘ object has no attribute ‘reshape‘处…...
docker-compose手册
大家好,我叫徐锦桐,个人博客地址为www.xujintong.com。平时记录一下学习计算机过程中获取的知识,还有日常折腾的经验,欢迎大家访问。 前言 一些自己经常用到的docker-compose知识。 一、运行和启动项目 1.1、docker-compose运行…...
【珠峰 WEB 前端架构师课程】学习笔记 100 篇(完结)
该课程是珠峰姜文老师讲的,个人觉得讲的很不错,一路在 b 站学习下来做了 100 篇的学习笔记,收获颇丰。 该课程主要讲了高阶函数、函数柯里化、发布订阅模式、观察者模式、从 0 到 1 实现一个 promise,co 库的实现、eventloop 执行…...
Java线程中sleep()、wait()、yield()、join()方法的使用
1.sleep() sleep(): sleep 方法属于 Thread 类,该行为中线程不会释放锁,只阻塞线程,让出cpu给其他线程,当达到指定的时间后会自动恢复运行状态继续运行。 2.wait() wait(): 该方法属于 Object 类,在这个过程里线程会…...
【机器学习】数据均衡学习笔记
文章目录 序言1. 样本不均衡2. 样本不均衡的影响以及样本均衡的意义3. 什么时候需要进行样本均衡/数据均衡4. 数据不均衡的解决办法 序言 数据集制作过程中需要关注样本均衡问题,学习笔记,简单记录 1. 样本不均衡 分类任务中不同类别样本数差别很大的…...
【软件教程】如何用C++交叉编译出能在Android运行的ELF程序或so动态库
一、配置NDK交叉编译平台 1. 打开Android的官方ndk下载链接https://developer.android.com/ndk/downloads?hlzh-cn,下载windows 64位ndk环境包。 2. 解压后将具有以下文件的路径加入到系统环境变量。 3. 配置好环境变量,如下图所示,Path中存…...
进阶JAVA篇- Map 系列集合的遍历方法与常用API
目录 1.0 Map 集合的说明 1.1 Map 集合的常用方法 1.2 Map 系列集合的特点 2.0 Map 系列集合的遍历方法(三种方法) 2.1 使用 keySet() 方法遍历 2.2 使用 entrySet() 方法遍历 2.3 使用 forEach() 方法遍历(Java 8) 1.0 Map 集合的…...
Auth.js:多合一身份验证解决方案 | 开源日报 No.60
nodejs/node Stars: 96.2k License: NOASSERTION Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。它具有以下关键特性和核心优势: 强大:Node.js 提供了强大且高效的服务器端运行能力,可以处理并发请求,并支持异步编程…...
SpringBoot整合Activiti7——任务监听器(七)
文章目录 一、任务监听器事件类型配置方式(选)代码实现xml文件创建监听器class方式expression方式delegateExpression 测试流程部署流程启动流程完成任务 一、任务监听器 任务监听器可以在任务创建、任务分配、任务完成、任务删除发生时触发,从而执行相应的逻辑。 事…...
电解电容寿命与哪些因素有关?
电解电容在各类电源及电子产品中是不可替代的元器件,这些电子产品中由于应用环境的原因,使它成为最脆弱的一环,所以,电解电容的寿命也直接影响了电子产品的使用寿命。 一、电解电容失效模式与因素概述 铝电解电容器正极、负极引出…...
Opencv-图像插值与LUT查找表
图像像素的比较 白色是255,黑色是0 min(InputArray src1,InputArray src2,OutputArray dst) max(InputArray src1,InputArray src2,OutpurArray dstsrc1:第一个图像矩阵,通道数任意src2:第二个图像矩阵,尺寸和通道数以及数据类型…...
我为什么写博客?写博客给我带来了什么?
1、写博客的契机 (1)刚开始接触CSDN,是大三的时候开始学习嵌入式开发,经常需要到网上百度查资料,由此经常游览CSDN上的博客; (2)在嵌入式的过程中,需要总结学习过的知识。…...
jdk11的HttpClient
我们都知道在jdk11之前都在用okhttp或者org.apache.httpcomponents 其实早在jdk9的时候这个方案就在孵化中 上面的截图来自openjdk的官网,注:openjdk是个开源项目,不存在侵权现象 这是openjdk的官网:JEP 110: HTTP/2 Client (In…...
业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
