Leetcode: Merge k Sorted List
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example: Input: [ 1->4->5, 1->3->4, 2->6 ] Output: 1->1->2->3->4->4->5->6
参看别人的思路,类似MergeSort的思路,思路是先分成两个子任务,然后递归求子任务,最后回溯回来。这个题目也是这样,先把k个list分成两半,然后继续划分,直到剩下两个list就合并起来,合并时会用到Merge Two Sorted Lists这道题。
MergeSort的方法:我们来分析一下上述算法的时间复杂度。假设总共有k个list,每个list的最大长度是n,那么运行时间满足递推式T(k) = 2T(k/2)+O(n*k)。根据主定理,可以算出算法的总复杂度是O(nklogk)。空间复杂度的话是递归栈的大小O(logk)。
1 public class Solution { 2 public ListNode mergeKLists(ListNode[] lists) { 3 if (lists==null || lists.length==0) return null; 4 return mergeSort(lists, 0, lists.length-1); 5 } 6 7 public ListNode mergeSort(ListNode[] lists, int s, int e) { 8 if (s == e) { 9 return lists[s]; 10 } 11 else { 12 int m = (s + e)/2; 13 return merge(mergeSort(lists, s, m), mergeSort(lists, m+1, e)); 14 } 15 } 16 17 public ListNode merge(ListNode l1, ListNode l2) { 18 ListNode dummy = new ListNode(-1); 19 ListNode cur = dummy; 20 while (l1 != null && l2 != null) { 21 if (l1.val <= l2.val) { 22 cur.next = l1; 23 l1 = l1.next; 24 } 25 else { 26 cur.next = l2; 27 l2 = l2.next; 28 } 29 cur = cur.next; 30 } 31 cur.next = l1 != null ? l1 : l2; 32 return dummy.next; 33 } 34 }
参考https://segmentfault.com/a/1190000003718892
优先队列法:
复杂度
时间 O(NlogK) 空间 O(K),这里的N = n*k, 就是所有list里面的总的数的个数
思路
当我们归并k个列表时,最简单的方法就是,对于每次插入,我们遍历这K个列表的最前面的元素,找出K个中最小的再加入到结果中。不过如果我们用一个优先队列(堆),将这K个元素加入再找堆顶元素,每次插入只要logK的复杂度。当拿出堆顶元素后,我们再将它所在链表的下一个元素拿出来,放到堆中。这样直到所有链表都被拿完,归并也就完成了。
注意
因为堆中是链表节点,我们在初始化堆时还要新建一个Comparator的类
1 public class Solution { 2 public ListNode mergeKLists(ListNode[] lists) { 3 if(lists.length == 0) return null; 4 ListNode dummy = new ListNode(0); 5 PriorityQueue<ListNode> q = new PriorityQueue<ListNode>(11, new Comparator<ListNode>(){ 6 public int compare(ListNode n1, ListNode n2){ 7 return n1.val - n2.val; 8 } 9 }); 10 // 初始化大小为k的堆 11 for(int i = 0; i < lists.length; i++){ 12 if(lists[i] != null) q.offer(lists[i]); 13 } 14 ListNode curr = dummy; 15 while(!q.isEmpty()){ 16 // 拿出堆顶元素 17 curr.next = q.poll(); 18 curr = curr.next; 19 // 将堆顶元素的下一个加入堆中 20 if(curr.next != null){ 21 q.offer(curr.next); 22 } 23 } 24 return dummy.next; 25 } 26 }