[leetcode]Merge k Sorted Lists

Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

这道题,第一次刷是过了,第二次同样的代码超时了,看来case是在不断加强的

算法

思路1:

最土的算法,两个月前能过,现在TLE,同[leetcode]Merge Two Sorted Lists

首先把l1和l2合并到l1中,遍历2n个节点

再把合并之后的l1和l3合并到l1中,遍历3n个节点

再把合并之后的l1和l4合并到l1中,遍历4n个节点

....

最后把合并后的l1和lm合并到l1中,遍历m*n个节点

总共遍历了(2+3+...+m)*n个节点,时间复杂度为O(n*m^2)

代码如下:

 1   public ListNode mergeKLists(List<ListNode> lists) {
 2         if(lists == null || lists.size() == 0) return null;
 3         ListNode l1 = lists.get(0);
 4         for(int i = 1; i < lists.size(); i++)
 5             l1 = mergeTwoLists(l1,lists.get(i));
 6         return l1;
 7     }
 8     public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
 9         if(l1 == null) return l2;
10         if(l2 == null) return l1;
11         ListNode head = new ListNode(1);
12         head.next = l1;
13         ListNode pre = head;
14         ListNode node = l2;
15         while(l2 != null){
16             node = l2;
17             while(pre.next != null && pre.next.val <= node.val){
18                 pre = pre.next;
19             }
20             l2 = node.next;
21             node.next = pre.next;
22             pre.next = node;
23             pre = node;
24         }
25         return head.next;
26     }
View Code

思路2:

分治法,将m个list分成两拨list1,list2,对每一拨分别处理

当list.size() = 1时,直接返回, size() = 2时候,即:merge2ListNode

处理完list1 和list2之后,再把二者合并

时间负责度O(n*klogk)【其中k为list.size()】

代码如下:

 1 public class Solution {
 2     public ListNode mergeKLists(List<ListNode> lists) {
 3         if(lists == null || lists.size() == 0) return null;
 4         if(lists.size() == 1) return lists.get(0);
 5         if(lists.size() == 2){
 6             return merge2List(lists.get(0), lists.get(1));
 7         }
 8         List<ListNode> l1 = new ArrayList<ListNode>();
 9         List<ListNode> l2 = new ArrayList<ListNode>();
10         for(int i = 0;i < lists.size() ; i++){
11             if(i < lists.size() / 2) l1.add(lists.get(i));
12             else l2.add(lists.get(i));
13         }
14         ListNode list1 = mergeKLists(l1);
15         ListNode list2 = mergeKLists(l2);
16         return merge2List(list1, list2);
17     }
18     private ListNode merge2List(ListNode l1,ListNode l2){
19         ListNode head = new ListNode(1);
20         head.next = l1;
21         ListNode pre = head;
22         ListNode node = l2;
23         while(l2 != null){
24             node = l2;
25             while(pre.next != null && pre.next.val <= node.val){
26                 pre = pre.next;
27             }
28             l2 = node.next;
29             node.next = pre.next;
30             pre.next = node;
31             pre = node;
32         }
33         return head.next;
34     }
35 }
View Code

思路3:

堆,由于对堆不熟悉,所以写出来的代码很丑,不过好歹AC了,时间复杂度同分治法,明天过来再优化一下:

渣代码如下:

 1 public class Solution {
 2     public ListNode mergeKLists(List<ListNode> lists) {
 3         if(lists == null || lists.size() == 0) return null;
 4         int k = 0;
 5         List<ListNode> list = new ArrayList<ListNode>();
 6         for(int i = 0; i < lists.size(); i++){
 7             if(lists.get(i) != null) {
 8                 k++;
 9                 list.add(lists.get(i));
10             }
11         }
12         if(k == 0) return null;
13         if(k == 1) return list.get(0);
14         ListNode[] heap = new ListNode[k];
15         for(int i = 0 ; i < k ; heap[i] = list.get(i),i++);
16         for(int i = k / 2  - 1; i >= 0; i--){
17             adjustHeap(heap, k, i);
18         }
19         ListNode result = new ListNode(0);
20         ListNode tail = result;
21         while(true){
22             if(heap[0] == null){
23                 heap[0] = heap[k - 1];
24                 k--;
25             }
26             adjustHeap(heap, k, 0);
27             tail.next = heap[0];
28             if(k == 0) break;
29             heap[0] = heap[0].next;
30             tail = tail.next;
31         }
32         return result.next;
33     }
34     private void adjustHeap(ListNode[] heap,int size,int i){
35         while( 2 * i + 1 < size ){
36             ListNode left = heap[2 * i + 1];
37             if(left == null) return;
38             if(2 * i + 2 < size){
39                 ListNode right = heap[2 * i + 2];
40                 if(right.val <= left.val && right.val < heap[i].val){
41                     ListNode tem = right;
42                     heap[2 * i + 2] = heap[i];
43                     heap[i] = tem;
44                     i = 2 * i + 2;
45                 }else if(left.val <= right.val && left.val < heap[i].val){
46                     ListNode tem = left;
47                     heap[2 * i + 1] = heap[i];
48                     heap[i] = tem;
49                     i = 2 * i + 1;
50                 }else return;
51             }else{
52                 if(left.val < heap[i].val){
53                     ListNode tem = left;
54                     heap[2 * i + 1] = heap[i];
55                     heap[i] = tem;
56                 }
57                 return;
58             }
59         }
60     }
61     
62 }
View Code

第二遍:

 使用PriorityQueue的算法更简单一点,不过需要注意要定义比较器

代码如下:

 1 public class Solution {
 2     public ListNode mergeKLists(List<ListNode> lists) {
 3         if(lists == null || lists.size() == 0) return null;
 4         Queue<ListNode> pq = new PriorityQueue<ListNode>(20,new Comparator<ListNode>(){
 5             @Override
 6             public int compare(ListNode a,ListNode b){
 7                 return a.val - b.val;
 8             }
 9         });
10         ListNode newHead = new ListNode(0);
11         ListNode tail = newHead;
12         for(ListNode head : lists){
13             if(head != null) pq.offer(head);
14         }
15         while(!pq.isEmpty()){
16             ListNode node = pq.poll();
17             tail.next = node;
18             if(node.next != null) pq.offer(node.next);
19             node.next = null;
20             tail = node;
21         }
22         return newHead.next;
23     }
24 }
View Code

参考资料:

原文地址:https://www.cnblogs.com/huntfor/p/3855727.html