LeetCode 热题 HOT 100:链表专题
LeetCode 热题 HOT 100:https://leetcode.cn/problem-list/2cktkvj/
文章目录
- 2. 两数相加
- 19. 删除链表的倒数第 N 个结点
- 21. 合并两个有序链表
- 23. 合并 K 个升序链表
- 141. 环形链表
- 142. 环形链表 II
- 148. 排序链表
- 160. 相交链表
- 206. 反转链表
- 234. 回文链表
2. 两数相加
题目链接:https://leetcode.cn/problems/add-two-numbers/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
实现步骤:
- 将两个链表看成是相同长度的进行遍历,如果一个链表较短则在前面补 0,比如:987 + 23 = 987 + 023 = 1010。
- 每一位计算的同时需要考虑上一位的进位问题,而当前位计算结束后同样需要更新进位值。
- 如果两个链表全部遍历完毕后,进位值为 1,则在新链表最前方添加节点。
class Solution {public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode pre = new ListNode(0);ListNode p1 = l1, p2 = l2, q = pre;int sign = 0;while(p1 != null || p2 != null){int sum = 0;if(p1 == null){sum = p2.val + sign;p2 = p2.next;}else if(p2 == null){sum = p1.val + sign;p1 = p1.next;}else{sum = p1.val + p2.val + sign;p1 = p1.next;p2 = p2.next;}sign = sum >= 10 ? 1 : 0; // 修改标志位ListNode node = new ListNode(sum % 10);q.next = node;q = q.next;}if(sign == 1){ListNode node = new ListNode(1);q.next = node;}return pre.next;}
}
19. 删除链表的倒数第 N 个结点
题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode pre = new ListNode(0); // 伪头部节点pre.next = head;ListNode p, q;p = q = pre;int co = 0;while(q.next != null){ // 先让q指针先走n步,然后p指针再继续走if(++co > n){p = p.next;}q = q.next;}// 结束循环时,p指针指向倒数第N+1位p.next = p.next.next;// 注意避坑点:return head; 是存在问题的:当链表中只有一个元素时,p指针会进行删除后,head 还是指向原来的那个结点。return pre.next; }
}
21. 合并两个有序链表
题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode res = new ListNode(0);ListNode p = res;while(list1 != null && list2 != null){if(list1.val < list2.val){p.next = list1;list1 = list1.next;}else{p.next = list2;list2 = list2.next;}p = p.next;}p.next = list1 == null ? list2 : list1;return res.next;}
}
23. 合并 K 个升序链表
题目链接:https://leetcode.cn/problems/merge-k-sorted-lists/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
class Solution {public ListNode mergeKLists(ListNode[] lists) {ListNode head = null;for(int i = 0; i < lists.length; i ++){head = mergeTwoLists(head, lists[i]);}return head;}public ListNode mergeTwoLists(ListNode a, ListNode b){ListNode res = new ListNode(0);ListNode p = res;while(a!=null && b!=null){if(a.val < b.val){p.next = a;a = a.next;}else{p.next = b;b = b.next;}p = p.next;}p.next = a != null ? a : b;return res.next;}
}
141. 环形链表
题目链接:https://leetcode.cn/problems/linked-list-cycle/description/?envType=study-plan-v2&envId=top-100-liked
哈希表做法(时间复杂度较高):
public class Solution {public boolean hasCycle(ListNode head) {if(head == null){return false;}Set<ListNode> set = new HashSet(); // set 记录结点的地址while(head.next != null){if(set.contains(head)){return true;}set.add(head);head = head.next;}return false;}
}
快慢指针做法1:
public class Solution {public boolean hasCycle(ListNode head) {if(head == null){return false;}ListNode slow, fast;slow = head;fast = head.next;// slow 每次向前走一步,fast 每次向前走两步(可以任意多步)// 当存在环时,fast 由于走得快,会发生扣圈的情况,且最终与 slow 相遇// 当不存在环时,fast 可能在某次循环后,发生当前位置为空,或下一位置为空的两种情况,当然由于走的快,最终会返回false。// 总之,循环的结束条件,要么出现环 slow == fast,要么 fast 先一步为空! while(slow != fast && fast != null && fast.next != null){// 注意:fast != null 要先于fast.next != null 来判断,以防止控制帧异常slow = slow.next;fast = fast.next.next;}return slow == fast;}
}
快慢指针做法2(思路同下方“环形链表2”):
public class Solution {public boolean hasCycle(ListNode head) {ListNode slow = head, fast = head;while(true){if(fast==null || fast.next==null){return false;}slow = slow.next;fast = fast.next.next;if(slow==fast){return true;}}}
}
142. 环形链表 II
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/?envType=study-plan-v2&envId=top-100-liked
哈希表做法(时间复杂度较高):
public class Solution {public ListNode detectCycle(ListNode head) {Set<ListNode> set = new HashSet<>();ListNode p = head;while(p!=null){if(set.contains(p)){return p;}set.add(p);p = p.next;}return null;}
}
快慢指针,实现思路如下:
- 设
fast
每次走两个节点,slow
每次走一个节点。环外有a
个结点,环内有b
个结点。 - 相遇时,
fast
走了f
步,slow
走了s
步。
①f = 2s
②f = s + nb
表示f
比s
多走了n*b
步,即n
圈。这样表示的原因在于扣圈。
化简得:f = 2nb, s = nb
- 设刚开始
slow
指针从开始到环的入口要走 k 步:k = a + nb (n = 0,1,2,…)
- 由于
s = n*b
,即已经走了n*b
步了,那么此时只需要再走a
步即可回到链表入环的起点。
public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head, slow = head;while(true){if(fast == null || fast.next == null){return null;}fast = fast.next.next;slow = slow.next;if(fast == slow){break;}}fast = head; // fast回到链表起点,与 slow 一同遍历 a 步while(slow != fast){slow = slow.next;fast = fast.next;}return fast;}
}
148. 排序链表
题目链接:https://leetcode.cn/problems/sort-list/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
使用优先队列模仿堆:
class Solution {public ListNode sortList(ListNode head) {PriorityQueue<ListNode> queue = new PriorityQueue<>((a, b) -> b.val-a.val); // 大顶堆while(head != null){queue.offer(head); // 从堆底插入head = head.next;}ListNode pre = new ListNode(0);while(!queue.isEmpty()){ListNode p = queue.poll(); // 出队列并调整堆p.next = pre.next; // 头插法倒序pre.next = p;}return pre.next;}
}
自顶向下归并排序1: 时间复杂度 O(nlogn),空间复杂度O(logn)
class Solution {public ListNode sortList(ListNode head) {return mergeSort(head, null);}// 归并排序// 将头指针和尾指针之前的元素进行排序,初始尾指针为null,即最后一个节点的下一个空节点public ListNode mergeSort(ListNode head, ListNode tail){if(head == tail){return head;}if(head.next == tail){ // 隔离出来单独结点head.next = null;return head;}ListNode slow, fast;slow = fast = head;while(fast != tail){slow = slow.next;fast = fast.next;if(fast != tail){fast = fast.next;}}ListNode mid = slow;ListNode l1 = mergeSort(head, mid); // 将 head 至 mid 之前的节点进行排序ListNode l2 = mergeSort(mid, tail); // 将 mid 至 tail 之前的节点进行排序return mergeList(l1, l2);}// 合并两个有序链表public ListNode mergeList(ListNode l1, ListNode l2){ListNode pre = new ListNode(0);ListNode p = pre;while(l1 != null && l2 != null){if(l1.val < l2.val){p.next = l1;l1 = l1.next;}else{p.next = l2;l2 = l2.next;}p = p.next;}p.next = l1 == null ? l2:l1;return pre.next;}
}
参考链接:https://leetcode.cn/problems/sort-list/solutions/492301/pai-xu-lian-biao-by-leetcode-solution/?envType=featured-list&envId=2cktkvj%3FenvType%3Dfeatured-list&envId=2cktkvj
自顶向下归并排序2:
class Solution {public ListNode sortList(ListNode head) {return mergeSort(head);}// 归并排序public ListNode mergeSort(ListNode head){if(head==null || head.next==null){return head;}ListNode slow = head; // 快慢指针ListNode fast = head.next;while(fast!=null && fast.next!=null){ // 查询中间节点slow = slow.next;fast = fast.next.next;}ListNode mid = slow.next; // 断链slow.next = null;ListNode l1 = mergeSort(head);ListNode l2 = mergeSort(mid);return mergeList(l1, l2);}// 合并两个有序链表public ListNode mergeList(ListNode l1, ListNode l2){ListNode pre = new ListNode(0);ListNode p = pre;while(l1 != null && l2 != null){if(l1.val < l2.val){p.next = l1;l1 = l1.next;}else{p.next = l2;l2 = l2.next;}p = p.next;}p.next = l1 == null ? l2:l1;return pre.next;}
}
自底向上排序: 时间复杂度 O(nlog),空间复杂度O(n)
class Solution {public ListNode sortList(ListNode head) {ListNode pre = new ListNode(0);pre.next = head;int len = getLength(head); // 获取长度for(int step = 1; step < len; step *=2){ //依次将链表分块的长度分为:1,2,4...ListNode curr = pre.next;ListNode p = pre;// p 用于链接每次分块的链表,如:第一次循环链接分块长度为1的链表,然后链接分块长度为2的链表while(curr != null){ListNode h1 = curr; // 第一块链表的头ListNode h2 = spilt(h1, step); // 第二块链表的头curr = spilt(h2, step); // 下次while循环的头,也是给到h1// 合并第一二块链表,下次while循环合并第三四块链表....ListNode res = mergeList(h1, h2);// 将合并后的链表链接起来,并将指针移到链表的最后一个节点,以链接下次的链表p.next = res;while(p.next!=null){p = p.next;}}}return pre.next;}// 分割链表,并返回后半段的链头public ListNode spilt(ListNode head, int step){if(head == null){return null;}ListNode p = head;for(int i = 1; i < step && p.next!=null; i ++){p = p.next;}ListNode right = p.next;p.next = null; // 切断连接return right;}// 求链表长度public int getLength(ListNode head){int co = 0;while(head!=null){co++;head = head.next;}return co;}// 合并两个升序链表public ListNode mergeList(ListNode l1, ListNode l2){ListNode pre = new ListNode(0);ListNode p = pre;while(l1 != null && l2 != null){if(l1.val < l2.val){p.next = l1;l1 = l1.next;}else{p.next = l2;l2 = l2.next;}p = p.next;}p.next = l1 == null ? l2:l1;return pre.next;}
}
160. 相交链表
题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
实现步骤:
- 设不是公共部分的节点数分别是
a、b
,公共节点数为n
。 - 如果有公共节点,则当
p1
遍历完a+n
个节点时,再在另一个链表的头部遍历b
个节点时,必相交。原因在于此时p2
遍历了b+n+a
个结点。 - 如果没有公共节点部分,那么
p1
与p2
经历了上文的步骤后,都会为null
,null==null
为true
。
因此跳出循环,要么null == null
,要么都不为空找到了公共节点。
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode p1 = headA;ListNode p2 = headB;while(p1 != p2){p1 = p1 == null ? headB : p1.next;p2 = p2 == null ? headA : p2.next;}return p1;}
}
206. 反转链表
题目链接:https://leetcode.cn/problems/reverse-linked-list/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
class Solution {public ListNode reverseList(ListNode head) {ListNode pre = new ListNode(0);ListNode p = head;while(p!=null){ListNode q = p.next;p.next = pre.next;pre.next = p;p = q;}return pre.next;}
}
234. 回文链表
题目链接:https://leetcode.cn/problems/palindrome-linked-list/?envType=featured-list&envId=2cktkvj?envType=featured-list&envId=2cktkvj
class Solution {public boolean isPalindrome(ListNode head) {Deque<ListNode> stack = new LinkedList<>();ListNode p = head;while(p!=null){stack.push(p);p = p.next;}while(head != null){p = stack.pop();if(p.val != head.val){return false;}head = head.next;}return true;}
}
相关文章:
LeetCode 热题 HOT 100:链表专题
LeetCode 热题 HOT 100:https://leetcode.cn/problem-list/2cktkvj/ 文章目录 2. 两数相加19. 删除链表的倒数第 N 个结点21. 合并两个有序链表23. 合并 K 个升序链表141. 环形链表142. 环形链表 II148. 排序链表160. 相交链表206. 反转链表234. 回文链表 2. 两数相…...

Redis发布订阅
在现代的软件开发中,数据存储和管理是至关重要的一环。Redis,作为一个开源的、内存中的数据结构存储系统,以其出色的性能和灵活的数据结构,赢得了开发者们的广泛喜爱。它不仅可以用作数据库,还可以用作缓存和消息代理。…...

在Windows操作系统上安装PostgreSQL数据库
在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 一、在Windows操作系统上安装PostgreSQL数据库 点击 PostgreSQL可跳转至PostGreSQL的官方下载地址。 (1) (2)选择安装的目录ÿ…...

【云原生】Kubeadmin部署Kubernetes集群
目录 编辑 一、环境准备 1.2调整内核参数 二、所有节点部署docker 三、所有节点安装kubeadm,kubelet和kubectl 3.1定义kubernetes源 3.2开机自启kubelet 四、部署K8S集群 4.1查看初始化需要的镜像 4.2在 master 节点上传 v1.20.11.zip 压缩包至 /opt 目录…...

Java中wait和notify详解
线程的调度是无序的,随机的,但是也是有一定的需求场景,希望能够有序执行,join算是一种控制顺序的方式(功能有限)——》一个线程执行完,才能执行另一个线程! 本文主要讲解的…...

算法竞赛个人注意事项
浅浅记录一下自己在算法竞赛中的注意事项。 数据类 注意看数大小,数学库中的函数尽量加上 * 1.0,转成double,防止整型溢出。,int型相乘如果可能溢出,乘 * 1LL。 数据范围大于1e6,注意用快读。 浮点数输…...
ClickHouse和Doris超大数据集存储
文章目录 一. ClickHouse1. 性能2. 可靠性3. 可扩展性4. 支持SQL和复杂查询5. 适用场景 二. Doris1. 性能2. 可靠性3. 易用性4. 适用场景 三. ClickHouse和Doris的比较1. 架构2. 性能3. 可靠性4. 易用性5. 适用场景 四. 总结 ClickHouse和Doris是两种流行的超大数据集存储方案。…...

02-Flask-对象初始化参数
对象初始化参数 前言对象初始化参数import_namestatic_url_pathstatic_foldertemplate_floder 前言 本篇来学习Flask中对象初始化参数 对象初始化参数 import_name Flask程序所在的包(模块),传__name__就可以 _name_ 是一个标识 Python 模块的名字的变量&#x…...

第5篇 vue的通信框架axios和ui框架-element-ui以及node.js
一 axios的使用 1.1 介绍以及作用 axios是独立于vue的一个项目,基于promise用于浏览器和node.js的http客户端。 在浏览器中可以帮助我们完成 ajax请求的发送在node.js中可以向远程接口发送请求 1.2 案例使用axios实现前后端数据交互 1.后端代码 2.前端代码 &…...

RabbitMQ 知识点解读
1、AMQP 协议 1.1、AMQP 生产者的流转过程 当客户端与Broker 建立连接的时候,会调用factory .newConnection 方法,这个方法会进一步封装成Protocol Header 0-9-1 的报文头发送给Broker ,以此通知Broker 本次交互采用的是AMQPO-9-1 协议&…...

SimVODIS++: Neural Semantic Visual Odometry in Dynamic Environments 论文阅读
论文信息 题目:SimVODIS: Neural Semantic Visual Odometry in Dynamic Environments 作者:Ue-Hwan Kim , Se-Ho Kim , and Jong-Hwan Kim , Fellow, IEEE 时间:2022 来源: IEEE ROBOTICS AND AUTOMATION LETTERS(RAL…...

7.Xaml Image控件
1.运行图片 2.运行源码 a.xaml源码 <!--Source="/th.gif" 图像源--><!--Stretch="Fill" 填充模式--><Image x:Name...

Solidity 小白教程:11. 构造函数和修饰器
Solidity 小白教程:11. 构造函数和修饰器 这一讲,我们将用合约权限控制(Ownable)的例子介绍solidity语言中构造函数(constructor)和独有的修饰器(modifier)。 构造函数 构造函数&…...

静态工厂模式,抽象工厂模式,建造者模式
静态工厂模式 ublic class FruitFactory {public static Fruit getFruit(String name) {Fruit fnull;switch (name){case "APPLE":{fnew Apple();}case "BANANA":{fnew Banana();}default :{System.out.println("Unknown Fruit");}}return f;} …...

【动手学深度学习笔记】--门控循环单元GRU
文章目录 门控循环单元GRU1.门控隐状态1.1重置门和更新门1.2候选隐状态1.3隐状态 2.从零开始实现2.1读取数据2.2初始化模型参数2.3定义模型2.4训练与预测 3.简洁实现 门控循环单元GRU 学习视频:门控循环单元(GRU)【动手学深度学习v2】 官方…...

浅析linux异步io框架 io_uring
前言 Linux内核5.1支持了新的异步IO框架iouring,由Block IO大神也即Fio作者Jens Axboe开发,意在提供一套公用的网络和磁盘异步IO,不过io_uring目前在磁盘方面要比网络方面更加成熟。 目录 背景简介 io_uring 系统API liburing 高级特性…...
访问者模式的一个使用案例——文档格式转换
访问者模式的一个使用案例——文档格式转换 假设我们在开发一个文档编辑器,它支持多种不同的文档元素(如段落、图片、表格等),现在我们需要添加一个功能——将文档导出为 HTML 或 Markdown 格式。 这就是一个典型的访问者模式的…...

【MySql】数据库的聚合查询
写在最前面的话 哈喽,宝子们,今天给大家带来的是MySql数据库的聚合查询。在前面CRUD章节我们学习了表达式查询,表达式查询是针对列和列之间进行运算的,那么如果想在行和行之间进行运算,那么就需要用到聚合查询。聚合查…...

Linux初探 - 概念上的理解和常见指令的使用
目录 Linux背景 Linux发展史 GNU 应用场景 发行版本 从概念上认识Linux 操作系统的概念 用户的概念 路径与目录 Linux下的文件 时间戳的概念 常规权限 特殊权限 Shell的概念 常用指令 ls tree stat clear pwd echo cd touch mkdir rmdir rm cp mv …...
苹果上架Guideline 4.3 - Design
最近上架苹果商店,审核提示 Guideline 4.3 - DesignWe noticed your app shares a similar binary, metadata, and/or concept as apps previously submitted by a terminated Apple Developer Program account.Submitting similar or repackaged apps is a form o…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...