23. 合并K个升序链表
- 我们可以模仿合并两个链表的那样,扩展到多维,但为了快速比较哪个小,使用优先队列来判断。
- 使用归并,两两合并,再最终合并
但需要考虑的点是:如何像合并两个链表那样知道指针移动方向?
实际上是因为本题是链表:当用优先队列pop出元素的时候,元素里面自带移动方向,使用.next指针加入队列即可,但如果不是链表,是数组呢?
可以增加一个临时类:
public class Node{
int index;//标记数组位置
int flag;//标记哪个数组
int value;//标记值
}
每次修改值再加入就行了,如下:
设数组为nums[][]
PriorityQueue<Node> pq = new PriorityQueue<>(((o1, o2) -> o1.val-o2.val));
List<Integer> ans = new ArrayList<>();
while(!pq.isEmpty()){
Node cur = pq.poll();
ans.add(cur.val)
cur.index++;
if(cur.index<nums[cur.flag].length){
cur.val=nums[cur.flag][cur.index];
pq.offer(cur);
}
}
但实际上,当是数组的时候,采用两两归并也是一种很不错的想法,但使用的空间复杂度也不低,操作也比较麻烦,可以考虑上面描述的方法。
回归本题,下面给出使用优先队列的解法:
public ListNode mergeKLists(ListNode[] lists) {
ListNode pre = new ListNode(-1);
ListNode tp = pre;
PriorityQueue<ListNode> pq = new PriorityQueue<>(((o1, o2) -> o1.val-o2.val));
for (ListNode list : lists) {
if (list!=null) pq.offer(list);
}
while (!pq.isEmpty()) {
ListNode cur = pq.poll();
tp.next = cur;
if (cur.next != null) pq.offer(cur.next);
tp = tp.next;
tp.next = null;
}
return pre.next;
}