题解 | #合并k个已排序的链表#
合并k个已排序的链表
https://www.nowcoder.com/practice/65cfde9e5b9b4cf2b6bafa5f3ef33fa6
合并k个已排序的链表
目标
我们需要把很多条按从小到大排列的珠子串(链表)合并成一条新的珠子串,这条新的珠子串也要按从小到大的顺序排列。
示例
假设我们有三条珠子串:
- 第一条珠子串:
1 → 2
- 第二条珠子串:
1 → 4 → 5
- 第三条珠子串:
6
我们要把这三条珠子串合并成一条新的珠子串,这条珠子串也要按从小到大的顺序排列。
解释步骤
1. 准备一个“假头”珠子
我们先在新珠子串的最前面放一个“假头”珠子,这个珠子实际上不参与最终的珠子串,但可以帮助我们更容易地开始合并。
ListNode dummy = new ListNode(0); // “假头”珠子 ListNode tail = dummy; // 用来记录新珠子串的最后一个珠子
2. 创建一个“魔法盒子”
想象一下,我们有一个“魔法盒子”,这个盒子可以自动把珠子按从小到大的顺序排好。这个“魔法盒子”其实就是一个叫做“优先队列”的工具。
PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);
3. 把每条珠子串的第一个珠子放进“魔法盒子”
我们从每条珠子串的开头开始,把每条珠子串的第一个珠子放进“魔法盒子”里。
for (ListNode list : lists) { if (list != null) { pq.add(list); // 把第一个珠子放进去 } }
4. 从“魔法盒子”里拿出最小的珠子
我们不断地从“魔法盒子”里拿出最小的珠子,然后把这个珠子放到新珠子串里。
while (!pq.isEmpty()) { // 从“魔法盒子”里拿出最小的珠子 ListNode minNode = pq.poll(); // 把这个珠子放到新珠子串里 tail.next = minNode; tail = tail.next; // 如果这个珠子后面还有珠子,就把后面的珠子也放进“魔法盒子” if (minNode.next != null) { pq.add(minNode.next); } }
5. 返回新珠子串的头珠子
最后,我们返回新珠子串的第一个珠子(实际上是“假头”珠子的下一个珠子)。
return dummy.next;
示例解析
假设我们有以下三条珠子串:
- 第一条珠子串:
1 → 2
- 第二条珠子串:
1 → 4 → 5
- 第三条珠子串:
6
- 初始化:
- 创建“假头”珠子 dummy。
- 创建“魔法盒子” pq。
- 把每条珠子串的第一个珠子放进“魔法盒子”:1, 1, 6。
- 不断从“魔法盒子”里拿出最小的珠子:
- 取出最小珠子 1,放到新珠子串里,然后检查是否有下一个珠子,如果有则放进“魔法盒子”。
- 再次取出最小珠子 1,放到新珠子串里,然后检查是否有下一个珠子,如果有则放进“魔法盒子”。
- 取出最小珠子 2,放到新珠子串里,然后检查是否有下一个珠子,如果没有则继续。
- 取出最小珠子 4,放到新珠子串里,然后检查是否有下一个珠子,如果有则放进“魔法盒子”。
- 取出最小珠子 5,放到新珠子串里,然后检查是否有下一个珠子,如果没有则继续。
- 取出最小珠子 6,放到新珠子串里,然后检查是否有下一个珠子,如果没有则继续。
- 返回结果:
- 返回合并后的珠子串的头珠子:{1, 1, 2, 4, 5, 6}。
这样,我们就得到了一条新的按从小到大排列的珠子串。
最后附上完整代码
import java.util.PriorityQueue; public class Solution { public ListNode mergeKLists(ListNode[] lists) { // 创建一个优先队列,按照节点值从小到大排序 PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val); // 初始化:将所有非空链表的头节点加入优先队列 for (ListNode list : lists) { if (list != null) { pq.add(list); } } // 创建虚拟头节点简化边界处理 ListNode dummy = new ListNode(0); ListNode tail = dummy; // 只要优先队列不为空,就继续合并 while (!pq.isEmpty()) { // 取出当前最小的节点 ListNode minNode = pq.poll(); // 将该节点加入到结果链表中 tail.next = minNode; tail = tail.next; // 如果该节点有下一个节点,将下一个节点加入优先队列 if (minNode.next != null) { pq.add(minNode.next); } } // 返回合并后的链表头节点 return dummy.next; } }#牛客创作赏金赛#
小学生都能看懂的算法 文章被收录于专栏
主要面向小白的算法文章。以小学生都能看懂为目标而编写,顺便巩固下自己。