zoukankan      html  css  js  c++  java
  • [Leetcode]Merge Two Sorted Lists&Merge k Sorted Lists随记

    No.21, Merge Two Sorted Lists

    No.23, Merge k Sorted Lists

    第一个题是合并两个已经排序的链表,第二个题是合并k个已经排序的链表。

    第一个题是第二个题的基础,代码只贴第二题的,其中包含了第一题的方法。

    第一个题比较简单,每次取链表中未合并的部分中两个最小值比较即可,将小的放入结果链表。如果其中一个链表已经合并完成(即剩余的为空),则把另一个链表剩余的部分直接放在结果链表的最后。最坏情况下要比较m+n-1次(两个链表的长度为m,n)。

    第二题,有两种思路,一种是两两合并,一种是K个链表一起比较。

    第一种思路,也有不同的实现方案,一种是从第一个开始,顺序向下合并;另一种是按照二分的方法合并,例如一共有4个链表,lists[0]和lists[2]合并,lists[1]和lists[3]合并,再将这两个合并的结果进行合并,得到最终的结果。这两种方案复杂度是不一样的,假设所有链表一共有n个数字。第一种方法要合并k-1次,最坏情况每次合并都要比较n-k次(第一个链表长度特别长,其他链表不为空且数字比第一个链表的都要大),那么复杂度为O(nk)。第二个方法,一共要比较logk轮,n个数字在每一轮中都会参与合并1次,这里可以想象为一个二叉树,每一层都包含了n个数字一次,高度为logk,那么这里复杂度为O(nlogk)。第一种方法提交会超时,第二种AC。

    public class Solution {
             public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
                ListNode result;
                if(l1==null)
                    return l2;
                if(l2==null)
                    return l1;
                if(l1.val<=l2.val){
                    result=new ListNode(l1.val);
                    l1=l1.next;
                }
                else{
                    result=new ListNode(l2.val);
                    l2=l2.next;
                }
                ListNode p=result;
                while(l1!=null||l2!=null){
                    if(l1==null||l2!=null&&l1.val>l2.val){
                        p.next=new ListNode(l2.val);
                        l2=l2.next;
                    }
                    else if(l2==null||l1!=null&&l1.val<=l2.val){
                        p.next=new ListNode(l1.val);
                        l1=l1.next;
                    }
                    p=p.next;
                }      
                return result;
            }
        public ListNode mergeKLists(ListNode[] lists) {
            int len=lists.length;
            if(len==0)
                return null;
            while(len>1){
                int point=(len+1)/2;
                for(int i=0;i<len/2;i++){
                    lists[i]=mergeTwoLists(lists[i],lists[i+point]);
                }
                len=point;
            }
            return lists[0];
        }
    }

    那么除了两两合并,还可以k个链表一起比较。这里需要使用最小堆或者优先级队列,原理差不多,以堆为例。首先这类带有优先级的数据结构,在插入一个新的值时,重新排序的复杂度为log(n),n为节点数。我们每次都把k个链表中未合并部分的最小值组成最小堆,堆的节点数为k,堆的第一层就是最小值,即需要拿去合并的值,该值拿走后需要再用同一个链表的下一值补充。这样一共需要进行n次(n还是全部链表的数字数量),因此复杂度还是O(nlogk)。

  • 相关阅读:
    常见寻找OEP脱壳的方法
    Windows内核原理系列01
    HDU 1025 Constructing Roads In JGShining's Kingdom
    HDU 1024 Max Sum Plus Plus
    HDU 1003 Max Sum
    HDU 1019 Least Common Multiple
    HDU 1018 Big Number
    HDU 1014 Uniform Generator
    HDU 1012 u Calculate e
    HDU 1005 Number Sequence
  • 原文地址:https://www.cnblogs.com/lilylee/p/5235528.html
Copyright © 2011-2022 走看看