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 }
原文地址:https://www.cnblogs.com/EdwardLiu/p/3783741.html