一、题目
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
二、思路
可以用小顶堆解答
小顶堆知识点
https://mp.weixin.qq.com/s/o7tdyLiYm668dpUWd-x7Lg
1.二叉堆概览
https://blog.csdn.net/u010224394/article/details/8834969
二叉堆是完全二叉树或者近似完全二叉树
二叉堆多数是以数组作为它们底层元素的存储,根节点在数组中的索引是1,存储在第n个位置的父节点它的子节点在数组中的存储位置为2n与2n+1,结果如下图所示
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ / \
8 9 10 11
满二叉树
满二叉树,除最后一层无任何子节点外,每一层上的所有结点都有两个子结点二叉树,如下所示
1
/ \
2 3
/ \ / \
4 5 6 7
完全二叉树
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
通俗理解就是,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
2.二叉堆分类
二叉堆分为最大堆和最小堆。
最大堆的性质是:每个节点都大于等于它的两个子节点。
最小堆的性质是:每个节点都小于等于它的子节点。
3.二叉堆的定义
https://blog.csdn.net/weixin_43207025/article/details/117754741?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.no_search_link&spm=1001.2101.3001.4242
https://www.liaoxuefeng.com/wiki/1252599548343744/1265120632401152#0
最小堆
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //不指定Comparator时默认为小顶堆(最小堆),默认容量为11
最大堆
PriorityQueue<Integer> heap = new PriorityQueue<>(
(w1, w2) -> w2 - w1 // 第二个参数减第一个是大顶堆
);
上面的构造函数等同于下面
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11
@Override
public int compare(Integer i1,Integer i2){
return i2-i1; //大顶堆执行poll()去掉的是大数,留下的是小数。构造方法传入(w1, w2) -> w2 - w1 // 第二个参数减第一个是大顶堆
}
});
4.二叉堆方法
https://www.cnblogs.com/lingq/p/12735318.html
PriorityQueue的常用方法有:poll(),offer(Object),size(),peek()等。
插入方法(offer()、poll()、remove() 、add() 方法)时间复杂度为O(log(n)) ;
remove(Object) 和 contains(Object) 时间复杂度为O(n);
检索方法(peek、element 和 size)时间复杂度为常量。
三、实现代码
/**
* 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{
ListNode mergeKLists (ListNode[] lists){
//异常情况
if (lists.length == 0) return null;
//定义最后存放数据的链表
ListNode result = new ListNode(-1); //虚拟头结点
ListNode p = result;
//定义小顶堆
PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length,(a,b)->(a.val-b.val));
//把k个链表的head放到小顶堆中
for (ListNode head:lists){
if(head!=null){
pq.add(head);
}
}
//逐个找k个结点的下一个节点,并存入链表
while (!pq.isEmpty()){
ListNode node = pq.poll();
p.next = node;
if (node.next !=null){
pq.add(node.next);
}
p = p.next;
}
return result.next;
}
}