难度:hard
方法一:
利用优先队列,得到k个链表中的最小节点,反复添加:
/**
* 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.length == 0) {
return null;
}
// 虚拟头结点
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
// 优先队列,最小堆
PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length, (a, b) -> (a.val - b.val));
// 将k个头结点加入最小堆
for (int i = 0; i < lists.length; i++) {
// 应对示例3的判断
if (lists[i] != null) {
pq.add(lists[i]);
}
// pq.add(lists[i]);
}
while (!pq.isEmpty()) {
// 获取堆中的最小节点
ListNode node = pq.poll();
cur.next = node;
cur = cur.next;
if (node.next != null) {
pq.add(node.next);
}
}
return dummy.next;
}
}
复杂度分析
时间复杂度:考虑优先队列中的元素不超过 k个,那么插入和删除的时间代价为 O(logk),这里最多有 kn 个点,对于每个点都被插入删除各一次,故总的时间代价即渐进时间复杂度为 O(kn×logk)。
空间复杂度:这里用了优先队列,优先队列中的元素不超过 k 个,故渐进空间复杂度为 O(k)。