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.

Show Tags
LeetCode: Merge k Sorted Lists 解题报告

参考资料: http://blog.csdn.net/linhuanmars/article/details/19899259。

SOLUTION 1:

使用分治法。左右分别递归调用Merge K sorted List,然后再使用merge linked list 合并在一起。

解答摘录如下:这 道题目在分布式系统中非常常见,来自不同client的sorted list要在central server上面merge起来。这个题目一般有两种做法,下面一一介绍并且分析复杂度。 第一种做法比较容易想到,就是有点类似于MergeSort的思路,就是分治法,不了解MergeSort的朋友,请参见归并排序-维基百科,是一个比较经典的O(nlogn)的排序算法,还是比较重要的。思路是先分成两个子任务,然后递归求子任务,最后回溯回来。这个题目也是这样,先把k个list分成两半,然后继续划分,知道剩下两个list就合并起来,合并时会用到Merge Two Sorted Lists这道题,不熟悉的朋友可以复习一下。代码如下:

 1 /*

 2         SOL 1:

 3           使用merge sort和分治法完成

 4     */

 5     public ListNode mergeKLists1(List<ListNode> lists) {

 6         // 记得加上这个合法性判断。

 7         if (lists == null || lists.size() == 0) {

 8             return null;

 9         }

10         

11         return helper(lists, 0, lists.size() - 1);

12     }

13     

14     /*

15     l, r表示list的左右边界

16     */

17     public ListNode helper(List<ListNode> lists, int l, int r) {

18         if (l < r) {

19             int mid = l + (r - l) / 2;

20             

21             /*

22                分治法。把问题分为2个更小的子问题:左边list的merge,和右边list的merge.

23                再把2个生成的解合并在一起。

24             */

25             return merge(helper(lists, l, mid), helper(lists, mid + 1, r));

26         }

27         

28         return lists.get(l);

29     }

30     

31     public ListNode merge(ListNode n1, ListNode n2) {

32         ListNode dummy = new ListNode(0);

33         ListNode cur = dummy;

34         

35         while (n1 != null && n2 != null) {

36             if (n1.val < n2.val) {

37                 cur.next = n1;

38                 n1 = n1.next;

39             } else {

40                 cur.next = n2;

41                 n2 = n2.next;

42             }

43             

44             cur = cur.next;

45         }

46         

47         if (n1 != null) {

48             cur.next = n1;

49         } else {

50             cur.next = n2;

51         }

52         

53         return dummy.next;

54     }
View Code

我们来分析一下上述算法的时间复杂度。假设总共有k个list,每个list的最大长度是n,那么运行时间满足递推式T(k) = 2T(k/2)+O(n*k)。根据主定理,可以算出算法的总复杂度是O(nklogk)。如果不了解主定理的朋友,可以参见主定理-维基百科。空间复杂度的话是递归栈的大小O(logk)。


SOLUTION 2:

接 下来我们来看第二种方法。这种方法用到了堆的数据结构,思路比较难想到,但是其实原理比较简单。维护一个大小为k的堆,每次取堆顶的最小元素放到结果中, 然后读取该元素的下一个元素放入堆中,重新维护好。因为每个链表是有序的,每次又是去当前k个元素中最小的,所以当所有链表都读完时结束,这个时候所有元 素按从小到大放在结果链表中。这个算法每个元素要读取一次,即是k*n次,然后每次读取元素要把新元素插入堆中要logk的复杂度,所以总时间复杂度是 O(nklogk)。空间复杂度是堆的大小,即为O(k)。代码如下:

 1 /*

 2         SOL 2:

 3           使用 priority Queue.

 4     */

 5     public ListNode mergeKLists(List<ListNode> lists) {

 6         // 记得加上这个合法性判断。

 7         if (lists == null || lists.size() == 0) {

 8             return null;

 9         }

10         

11         int size = lists.size();

12         

13         PriorityQueue<ListNode> q = new PriorityQueue<ListNode>(size, 

14             new Comparator<ListNode>() {

15                 // 注意,此处参数用ListNode

16                 public int compare(ListNode o1, ListNode o2) {

17                     return o1.val - o2.val;

18                 }

19             }

20         );

21         

22         // Add all the head node to the priority queue.

23         for (ListNode node: lists) {

24             if (node != null) {

25                 // Should skip the null node.s

26                 q.offer(node);    

27             }

28         }

29         

30         ListNode dummy = new ListNode(0);

31         ListNode tail = dummy;

32         

33         while (!q.isEmpty()) {

34             // get the smallest node from the queue.

35             ListNode cur = q.poll();

36             

37             tail.next = cur;

38             tail = tail.next;

39             

40             // 将下一个节点补充进来。

41             if (cur.next != null) {

42                 q.offer(cur.next);

43             }

44         }

45         

46         return dummy.next;

47     }
View Code

 

GITHUB:

https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/list/MergeKLists_1204.java

 

你可能感兴趣的:(LeetCode)