题目 leetcode23-合并K个升序链表
- 难度:hard;
- 字节半年出现:23 次;
思路
- 用 java 的优先级队列 PriorityQueue 维持一个小根堆 (不是非得用二叉树)
- 穿针引线(循环),不断的链接小根堆上最小的节点
- 看下图,谢一姐 她是我刷题的路的灯....
基础 与联想
- 基础知识:leetCode-21 合并两个有序链表
- java 的优先级队列 PriorityQueue
- 想想自己是不是刷过 leetcode 253 会议室
代码
/**
* 一姐的思路,我的注释
* @param lists
* @return
*/
public ListNode mergeKLists(ListNode[] lists) {
// 优先级队列, 用 ListNode[] 数组中,每个链表的头结点的 val 做比较;
// 小的放前面,大的放后面 (是不是有点像冒泡排序?)
PriorityQueue<ListNode> minHeap = new PriorityQueue<>((a, b) -> a.val - b.val);
// 将 数组参数lists 中的几点,全部放入优先级队列中 PriorityQueue
for (ListNode list : lists) {
// 当心测试 case 里面,放一个null 链表,
// 编程经验:不要相信别人传过来的参数,一定要做非法校验,
// 人家调一些非法参数,你的函数蹦了,那就你的问题;
// 而不是别人的问题。没办法,行走江湖,就是这么的残酷
if (list == null) {
continue;
}
// 放.....
minHeap.add(list);
}
// dummy 大法(不解释...我也不会解释...没空,,我要刷题,,,)
ListNode dummy = new ListNode(-1);
ListNode curr = dummy;
//
while (minHeap.size() != 0) {
// 1: 获取最小节点,不用怀疑,PripoQueue 队列 第 0 的位置已近是最小的节点了;
ListNode minNode = minHeap.remove();
// 2:将最小节点连接到 curr 的下一节点上(心里默念:穿针引线...)
curr.next = minNode;
// 3:当前节点后移一位(ps: 就是往前走一步)
curr = curr.next;
// 想一下,为啥可能为空的? 回头看第2步,curr 的 next 节点,是不是连接了 minNode 节点啊?
// minNode 是不是 会有下一个节点啊?为啥?我操?
// think again :minNode节点元素,最原始的数据,是不是 通过 for 循环遍历lists 数组放进去的啊?
// 这下,明白了吧
if (curr.next != null) {
// minNode 当点节点已经被 curr 的 next 节点连接上了,
// minHeap后面的节点还没有被使用,所有要将minHeap的下一个节点放到优先级队列中,
// 优先级队列会在内部对他们进行排列的(小泡泡放已经被放在队列的第 0 个位置了...不行自己 debug)
minHeap.add(minNode.next);
}
}
// 用 dummy 大法返回结果;
return dummy.next;
}