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…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...