力扣23(java)-合并k个升序链表(困难)
题目:
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] 按 升序 排列
lists[i].length 的总和不超过 10^4
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
参考@【王尼玛】的解题思路
一、小根堆
如图:4个链表中的最小值,一定来自黄色的部分,黄色的部分就是一个小根堆。
这个堆的元素个数是lists中链表的个数,初始时只是将每个链表的头结点放入堆中,建立完初始的堆后,就不断的从堆中获取节点,如果获取到的节点不为空,即还有下一个节点,那么就将下一个节点放到堆中。
代码:
1 /**
2 * Definition for singly-linked list.
3 * public class ListNode {
4 * int val;
5 * ListNode next;
6 * ListNode() {}
7 * ListNode(int val) { this.val = val; }
8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
9 * }
10 */
11 class Solution {
12 public ListNode mergeKLists(ListNode[] lists) {
13 if(lists == null || lists.length == 0) return null;
14 PriorityQueue<ListNode> queue = new PriorityQueue(new Comparator<ListNode>(){
15 public int compare(ListNode l1, ListNode l2){
16 //升序
17 return l1.val - l2.val;
18 }
19 });
20 ListNode dummy = new ListNode(0);
21 ListNode cur = dummy;
22 //把每个链表的头结点放进队列中
23 for(ListNode node: lists){
24 if(node != null){
25 queue.add(node);
26 }
27 }
28 while(!queue.isEmpty()){
29 cur.next = queue.poll();
30 cur = cur.next;
31 //将当前结点的下一个结点也放入队列中
32 if(cur.next != null){
33 queue.add(cur.next);
34 }
35 }
36 return dummy.next;
37 }
38 }
二、分治和合并
先将整个链表在中间进行拆分成两部分,然后再对这两部分继续拆分,直到拆分成最小单元(只有一个链表)时,再进行两两进行合并,合并后以当前合并后的链表为新的链表再与其他的链表进行合并。看图更容易理解
代码:
/**
* 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) {
if(lists == null || lists.length == 0) return null;
return mergeTwolists(lists, 0, lists.length - 1);
}
//分治
private ListNode mergeTwolists(ListNode[] lists, int start, int end){
if(start == end){
return lists[start];
}
int mid = start + (end - start) / 2;
ListNode l1 = mergeTwolists(lists, start, mid);
ListNode l2 = mergeTwolists(lists, mid+1, end);
return merge(l1, l2);
}
//合并
private ListNode merge(ListNode a, ListNode b){
if(a == null || b == null){
return (a == null) ? b : a;
}
if(a.val < b.val){
a.next = merge(a.next, b);
return a;
}else{
b.next = merge(a, b.next);
return b;
} }
}
小知识:
1.compare(Object o1, Object o2)
方法,比较o1和o2的大小:
如果要按照升序排序,
则 o1小于o2返回 -1,o1与o2相等返回 0,01大于02返回 1 如果要按照降序排序
则 o1小于o2返回 1,o1与o2相等返回 0,01大于02返回 -1
2.优先队列:优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序
常用方法:
peek()//返回队首元素
poll()//返回队首元素,队首元素出队列
add()//添加元素
size()//返回队列元素个数
isEmpty()//判断队列是否为空,为空返回true,不空返回false
优先队列中的元素可以默认自然排序
或者通过提供的Comparator(比较器)在队列实例化的时排序
。(不指定Comparator时默认为最小堆)
1 PriorityQueue<Integer> heap = new PriorityQueue<Integer>(new Comparator<Integer>() {
2 @Override
3 public int compare(Integer o1, Integer o2) {
4 //升序(小顶堆)
5 return o1 - o2;
6 或者这样写:
7 //降序(大顶堆)
8 return o2 - o1;
9 }
10 });
总结:
小顶堆, return
前减后(o1-o2);
大顶堆, return
后减前(o2-o1);
在堆中,比较器的使用方式为:若返回值>=0,则表示不要交换,否则,需要交换。所以我们只需要认清传入的两个参数,o1
和o2
哪一个是谁我们就可以控制其是否要交换,只需要记住,o1
永远是新的,在插入时是child
,删除时是parent。
力扣23(java)-合并k个升序链表(困难)的更多相关文章
- 浅谈归并排序:合并 K 个升序链表的归并解法
在面试中遇到了这道题:如何实现多个升序链表的合并.这是 LeetCode 上的一道原题,题目具体如下: 用归并实现合并 K 个升序链表 LeetCode 23. 合并K个升序链表 给你一个链表数组,每 ...
- 【每日一题】【小根堆&边出队边入队后续节点&注意判空】23. 合并K个升序链表-211128/220213
给你一个链表数组,每个链表都已经按升序排列. 请你将所有链表合并到一个升序链表中,返回合并后的链表. 答案1(参数是数组): /** * Definition for singly-linked li ...
- [LeetCode题解]23. 合并K个升序链表 | 分治 + 递归
方法一:分治 + 递归 解题思路 在21. 合并两个有序链表,我们知道如何合并两个有序链表.而本题是合并 k 个有序链表,可以通过大问题拆分成小问题解决,即把 k 个链表,拆分成 k/2 个链表组,俩 ...
- LeetCode-23 合并K个升序链表
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/merge-k-sorted-lists 题目描述 给你一个链表数组,每个链表都已经按升序排列. ...
- Leetcode(23)-合并K个排序链表
合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1-&g ...
- 【LeetCode】23. Merge k Sorted Lists 合并K个升序链表
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:合并,链表,单链表,题解,leetcode, 力扣,Py ...
- 力扣Leetcode 21. 合并两个有序链表
合并两个有序链表 将两个升序链表合并为一个新的升序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1-> ...
- 【LeetCode 23】合并K个排序链表
题目链接 [题解] 会归并排序吧? 就把这K个链表当成是K个数字就好. 然后做归并排序. 因为归并排序的时候本来就会有这么一个过程. [l..mid]和[mid+1..r]这两段区间都是有序的了已经. ...
- LeetCode-023-合并K个升序链表
合并K个升序链表 题目描述:给你一个链表数组,每个链表都已经按升序排列. 请你将所有链表合并到一个升序链表中,返回合并后的链表. 示例说明请见LeetCode官网. 来源:力扣(LeetCode) 链 ...
- Java实现 LeetCode 23 合并K个排序链表
23. 合并K个排序链表 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输 ...
随机推荐
- 常用Linux系统性能分析命令
Linux系统提供了许多命令来分析系统性能.以下是一些常用的Linux系统性能分析命令: top:实时监视系统的运行状态和进程信息,包括CPU使用率.内存使用情况.进程状态等. 实例:直接在终端中输入 ...
- k8s如何对外访问service
在Kubernetes(K8s)中,可以通过以下几种方式对外访问Service: 1.NodePort: 这是最常见的对外访问Service的方式.通过将Service的类型设置为NodePort,K ...
- posix API的一些理解
TCP Posix API的理解 我们主要从TCP连接讲解整个的流程. 连接的建立 消息的收发 连接的断开 连接的建立 先看一下一个TCP server的创建过程. #include<stdio ...
- 【Unity 3D游戏开发】在Unity使用NoSQL数据库方法介绍
随着游戏体积和功能的不断叠加,游戏中的数据也变得越来越庞杂,这其中既包括玩家产生的游戏存档等数据,例如关卡数.金币等,也包括游戏配置数据,例如每一关的配置情况.尽管Unity提供了PlayerPref ...
- 3DCAT首届行业生态交流会|瑞云科技技术总监赵志杰:实时渲染助力元宇宙应用触手可及
2021年12月17日下午,由深圳市瑞云科技有限公司主办,深圳市虚拟现实产业联合会协办的 云XR如何赋能元宇宙--3DCAT实时云渲染首届行业生态合作交流会 圆满落幕.此次活动围绕 "云XR ...
- 喜讯!瑞云科技被授予“海上扬帆”5G融合应用专委会成员单位
2022年7月19日,5G应用"海上扬帆"行动计划云启航大会暨"海上扬帆"融合应用专委会成立大会在沪成功举办. 受上海信通院工创中心邀请和信任,深圳市瑞云科技有 ...
- 记录--关于 HTML5 LocalStorage 的 5 个不为人知的事实
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 LocalStorage 是HTML5中一个方便使用的 API,它为 Web 开发人员 提供了一个易于使用的5MB的存储空间.使用 Loc ...
- 纯前端实现 JPG 图片压缩 | canvas
在线 Demo 体验地址 →: https://demos.sugarat.top/pages/jpg-compress/ 前言 在迭代图床应用时,需要用到图片压缩,在之前分享了使用 UPNG.js ...
- 【Pavia】遥感图像数据集下载地址和读取数据集代码
[Pavia]遥感图像数据集下载地址和读取数据集代码 目录 [Pavia]遥感图像数据集下载地址和读取数据集代码 前言 Pavia数据集 Pavia数据集地址: Pavia数据集预览 PaviaU.m ...
- KingbaseES V8R6 集群运维案例--麒麟系统bug导致sys_monitor.sh无法启动集群
案例说明: 麒麟信安操作系统,在部署了KingbaseES V8R6集群后,sys_monitor.sh在启动集群时,启动数据库服务失败,导致集群无法正常启动.后连接现场分析发现,此环境只要通过ssh ...