力扣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 ] 输 ...
随机推荐
- Vite-vue3 架构设计
Vite-vue3 架构设计 基础信息 Gitee项目地址:https://gitee.com/pengchenggang/vite-vue3 1 创建vite-vue3 初始化脚本 $ npm in ...
- 简单实用算法——二分查找法(BinarySearch)
目录 算法概述 适用情况 算法原理 算法实现(C#) 实际应用:用二分查找法找寻边界值 参考文章 算法概述 二分查找(英语:binary search),也叫折半查找(英语:half-interval ...
- 掌握Python库的Bokeh,就能让你的交互炫目可视化
本文分享自华为云社区<Bokeh图形魔法:掌握绘图基础与高级技巧,定制炫目可视化>,作者: 柠檬味拥抱. Bokeh是一个用于创建交互式可视化图形的强大Python库.它不仅易于使用,而且 ...
- cmd查看环境变量
1.查看当前所有可用的环境变量:输入 set 即可查看. 2.查看某个环境变量:输入 "set 变量名"即可,比如想查看path变量的值,即输入 set path 3.修改环境变量 ...
- Java诊断工具Arthas:开篇之watch实战
Arthas是阿里开源的线上监控诊断产品,用于问题的排查和诊断. 它的出现大大提高线上排查问题的效率,这篇只讲它一个非常牛逼的功能,其它功能往后篇章会在展开详细说. 一.Arthas能为你做什么? 1 ...
- 25_H.264编码
本文主要介绍一种非常流行的视频编码:H.264. 计算一下:10秒钟1080p(1920x1080).30fps的YUV420P原始视频,需要占用多大的存储空间? (10 * 30) * (1920 ...
- QT 智能指针 QPointer QScopedPointer QSharedPointer QWeakPointer QSharedDataPointer 隐式共享 显示共享
QPointer QPointer 使一种受保护的指针,当其引用的对象被销毁时,它会被自动清除(但是,销毁引用对象还是必须手动delete).QPointer所指向的对象必须是QObject或其派生类 ...
- AMD、request.js,生词太多,傻傻搞不清
前言 之前在公司用JS写前端页面,本来自己是一个写后端的,但是奈何人少,只能自己也去写了.但是自己对前端基本不懂,基本就是照着前人写的照着抄,反正大体意思是明白的,但是出现问题了,基本上也是吭哧吭哧好 ...
- ios应用免签+微信分身
一句话概括:用TrollStore自动加签安装微信ipa文件,实现ios上微信应用分身. 工具: 1. ios14.1 2. GTA Car Tracher 这个应用程序并不是真正的 GTA Car ...
- 存储过程 RETURN语句
1.RETURN 如果没有使用表达式,RETURN 命令用于告诉这个函数已经完成执行了,如示例2. 如果返回标量类型,那么可以使用任何表达式. 示例1: 带有表达式return CREATE OR R ...