zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Apache Shiro 使用手册(二)Shiro 认证
    jdk 环境变量
    IDEA 相关整理
    mysql 相关命令
    hbase 迁库移库步骤
    Linux 常用指令整理
    springboot aop + logback + 统一异常处理 打印日志
    查看jar包的jdk版本
    maven 将jar包推送到自己本机的maven库
    jar包内的文件导出的注意点
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/3783741.html
Copyright © 2011-2022 走看看