题目
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 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
题解
方式一:分治
public ListNode mergeKLists(ListNode[] lists) {
// 也可以遍历K个链表,每次合并i和i+1
return merge(lists, 0, lists.length - 1);
}
public ListNode merge(ListNode[] lists, int l, int r) {
if (l > r) {
return null;
}
if (l == r) {
return lists[l];
}
// 利用二分,成对处理链表
int mid = l + (r - l) / 2;
return mergeTowLists(merge(lists, l, mid), merge(lists, mid + 1, r));
}
// 原地合并两个升序链表,也可以利用新链表合并
public ListNode mergeTowLists(ListNode p, ListNode q) {
ListNode dummy = new ListNode();
ListNode tail = dummy;
while (p != null && q != null) {
if (p.val <= q.val) {
tail.next = p;
p = p.next;
} else {
tail.next = q;
q = q.next;
}
tail = tail.next;
}
tail.next = p == null ? q : p;
return dummy.next;
}
方式二:优先级队列
// 自定义对象实现比较器
class Node implements Comparable<Node> {
ListNode node;
Node(ListNode node) {
this.node = node;
}
@Override
public int compareTo(Node o2) {
// 升序,保证队列头取到的是最小的
return this.node.val - o2.node.val;
}
}
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<Node> queue = new PriorityQueue<>();
// 把K个链表头节点放入队列
for (ListNode list: lists) {
if (list != null) {
queue.offer(new Node(list));
}
}
ListNode dummy = new ListNode();
ListNode tail = dummy;
while (!queue.isEmpty()) {
// 取出最小的节点
Node node = queue.poll();
tail.next = node.node;
tail = tail.next;
// 如果没取完,将下一个节点放入队列
if (node.node.next != null) {
queue.offer(new Node(node.node.next));
}
}
return dummy.next;
}
总结
算法:分治
数据结构:优先级队列