LeetCode(23) - Merge k Sorted Lists

  题目和LeetCode(21)里merge two sorted List要求差不多,现在只是从2两个list变成了k个list。

  看到这个题,第一个反应是用一个heap(最大堆)把k个list里面的数存起来,然后一个一个poll出来生成一个新的list。遍历所有list要O(n),再堆里面插入元素,需要O(log(n))的时间,再生成新的List需要O(n),所以平均时间为O(nlog(n) + n),

  代码如下:

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) { val = x; }
 7  * }
 8  */
 9 public class Solution {
10     public ListNode mergeKLists(ListNode[] lists) {
11         ListNode dumpNode = new ListNode(0);
12         Queue<Integer> heap = new PriorityQueue<Integer>();
13         //把所有元素都放到heap里面。
14         for (ListNode head : lists) {
15             while (head != null) {
16                 heap.offer(head.val);
17                 head = head.next;
18             }
19         }
20         ListNode curr = dumpNode;
21         //生成新的list
22         while (!heap.isEmpty()) {
23             curr.next = new ListNode(heap.poll());
24             curr = curr.next;
25         }
26         return dumpNode.next;
27     }   
28 }

  这样做其实非常简单,但是鉴于这道题是一道hard的题,我估计这样做并不能够得到面试官的认可。首先,它并没有利用到每个list sorted的这一个性质,第二个,时间上也可以有更快的方法。

  怎么做呢?那就是利用了归并排序的特点,divide and conquer(分治)。首先是把相邻的两个list两两配对,利用LeetCode 21 merge two sorted list的方法,分别把它们merge起来,然后继续两两配对,知道merge到一个list为止。

  代码如下:

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode(int x) { val = x; }
 7  * }
 8  */
 9 public class Solution {
10     public ListNode mergeKLists(ListNode[] lists) {
11         ListNode res = mergeKListsHelper(lists,0,lists.length - 1);
12         return res;
13     }
14     
15     private ListNode mergeKListsHelper(ListNode[] lists, int left, int right) {
16         //返回条件的三种情况。
17         if (left > right) return null;
18         //没有配对上的list
19         if (left == right) return lists[left];
20         //当left和right相差一个时,把它们merge起来。
21         if (left + 1 == right) return mergeSortedList(lists[left],lists[right]);
22         //分治,对于每一堆list,中间分开,左右各自合并,最后再merge
23         int mid = (left + right) / 2;
24         ListNode leftNode = mergeKListsHelper(lists, left, mid-1);
25         ListNode rightNode = mergeKListsHelper(lists, mid, right);
26         return mergeSortedList(leftNode, rightNode);
27     }
28     
29     //merge两个list。和Leetcode 21一样。
30     private ListNode mergeSortedList(ListNode l1, ListNode l2) {
31         ListNode dumpNode = new ListNode(0);
32         ListNode curr = dumpNode;
33         while (l1 != null && l2 != null) {
34             if (l1.val < l2.val) {
35                 curr.next = new ListNode(l1.val);
36                 l1 = l1.next;
37             }
38             else {
39                 curr.next = new ListNode(l2.val);
40                 l2 = l2.next;
41             }
42             curr = curr.next;
43         }
44         
45         while (l1 != null) {
46             curr.next = new ListNode(l1.val);
47             l1 = l1.next;
48             curr = curr.next;
49         }
50         
51         while (l2 != null) {
52             curr.next = new ListNode(l2.val);
53             l2 = l2.next;
54             curr = curr.next;
55         }
56         
57         return dumpNode.next;
58     }
59 }
原文地址:https://www.cnblogs.com/kepuCS/p/5278633.html