zoukankan      html  css  js  c++  java
  • Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexit

    题目:

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

    这道题目在分布式系统中非常常见,来自不同client的sorted list要在central server上面merge起来。这个题目一般有两种做法,下面一一介绍并且分析复杂度。 第一种做法比较容易想到,就是有点类似于MergeSort的思路,就是分治法,不了解MergeSort的朋友,请参见 归并排序-维基百科,是一个比较经典的O(nlogn)的排序算法,还是比较重要的。思路是先分成两个子任务,然后递归求子任务,最后回溯回来。这个题目也是这样,先把k个list分成两半,然后继续划分,知道剩下两个list就合并起来,
    合并时会用到 Merge Two Sorted Lists 这道题,不熟悉的朋友可以复习一下。代码如下: 
     
     1 public class Solution {
     2 
     3     public ListNode mergeKLists(ListNode[] lists) {
     4         if(lists.length == 0) {
     5             return null;
     6         }
     7 
     8         return merge(0, lists.length-1, lists);
     9     }
    10 
    11     public ListNode merge(int i, int j, ListNode[] lists) {
    12         if(j < i) {
    13             return null;
    14         }
    15 
    16         if(i == j) {
    17             return lists[i];
    18         }
    19 
    20         int mid = (j-i)>>1 + i;
    21         ListNode l = merge(i, mid, lists);
    22         ListNode r = merge(mid+1, j, lists);
    23 
    24         ListNode dummy = new ListNode(0);
    25         ListNode runner = dummy;
    26 
    27         while(l != null && r != null) {
    28             if(l.val > r.val) {
    29                 runner.next = r;
    30                 r = r.next;
    31                 runner = runner.next;
    32             } else {
    33                 runner.next = l;
    34                 l = l.next;
    35                 runner = runner.next;
    36             }
    37         }
    38 
    39         if(l == null && r == null) {
    40             return dummy.next;
    41         }
    42 
    43         if(l == null) {
    44             runner.next = r;
    45         } else {
    46             runner.next = l;
    47         }
    48 
    49         return dummy.next;
    50     }
    51 }

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

    第二种方法:

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

    
    
     1 public class Solution {
     2 
     3     public ListNode mergeKLists(ArrayList<ListNode> lists) {
     4         PriorityQueue<ListNode> heap = new PriorityQueue<ListNode>(10, new Comparator<ListNode>(){
     5             public int compare(ListNode n1, ListNode n2) {
     6                 return n1.val - n2.val;
     7             }
     8         });
     9 
    10         for(int i = 0; i < lists.size(); i++) {
    11             ListNode node = lists.get(i);
    12             if(node != null) {
    13                 heap.offer(node);
    14             }
    15         }
    16 
    17         ListNode head = null;
    18         ListNode pre = head;
    19 
    20         while(head.size() > 0) {
    21             ListNode current = head.poll();
    22             if(head == null) {
    23                 head = null;
    24                 pre = head;
    25             } else {
    26                 pre.next = current;
    27             }
    28 
    29             pre = current;
    30             if(current.next != null) {
    31                 heap.offer(current.next);
    32             }
    33         }
    34 
    35         return head;
    36     }
    37 }
  • 相关阅读:
    洛谷P2089 烤鸡
    HDU-1000 A+B Problem
    《新标准C++程序设计》4.7-4.9(C++学习笔记17)
    《新标准C++程序设计》4.6(C++学习笔记16)
    面向对象程序设计寒假作业3
    《新标准C++程序设计》4.5(C++学习笔记15)
    《新标准C++程序设计》4.4(C++学习笔记14)
    《新标准C++程序设计》4.2-4.3(C++学习笔记13)
    洛谷题解P1047 校门外的树
    [lr] 矫正白平衡
  • 原文地址:https://www.cnblogs.com/wylwyl/p/10477891.html
Copyright © 2011-2022 走看看