Problems: https://leetcode.com/problems/merge-k-sorted-lists/
Solution1:
使用priorityQueue,将每个list的第一个值放入queue中,小的作为head,在取出的同时把node的下一个放入queue中
需要注意的是,要不断check node.next是否为空
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> queue = new PriorityQueue<>((a,b) -> a.val - b.val);
ListNode head = new ListNode(0);
ListNode cur = head;
for(ListNode list : lists) {
if(list != null) // 需要判断listNode是否为空
queue.add(list);
}
while(!queue.isEmpty()) {
cur.next = queue.poll();
if (cur.next.next != null) // 同样需要判断listNode是否为空
queue.add(cur.next.next);
cur = cur.next;
}
return head.next;
}
}
TC: O(nklogk)
n为listnode的长度,k为lists中list的个数
SC: O(k) + O(n)
O(k)为queue的长度,O(n)是输出占用的空间
Solution2:
活用递归 + divide and conquer
- 将lists不断拆成两两merge
- 两两merge的划分和merge中使用递归
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
return merge(lists, 0, lists.length-1);
}
// 将list两两merge
public ListNode merge(ListNode[] lists, int l, int r) {
if(l > r) return null; // left > right时,无list
if(l == r) return lists[l]; // left和right相等,返回当前list
if(l+1 == r) return merge2List(lists[l], lists[r]);// left到right只有两个list,直接调用merge2Lists
// 考虑多个list的情况(递归)
int mid = (l+r)/2; // 把lists二分
ListNode l1 = merge(lists, l, mid); // 前半部分merge
ListNode l2 = merge(lists, mid+1, r); // 后半部分merge
return merge2List(l1, l2);
}
// merge 2 lists
public ListNode merge2List(ListNode l1, ListNode l2) {
if(l1 == null) return l2;
if(l2 == null) return l1;
if(l1.val < l2.val) {
l1.next = merge2List(l1.next, l2);
return l1;
} else {
l2.next = merge2List(l1, l2.next);
return l2;
}
}
}
TC: O(nklogk)
merge list的过程实际上存在一个二叉树,高度是logk,每一层的计算量是nk
SC: O(logk)
用递归的话,SC只需要考虑递归深度,即二叉树的递归深度logk
Reference: https://www.youtube.com/watch?v=XqA8bBoEdIY&t=619s