zoukankan      html  css  js  c++  java
  • Algs4-2.2.12次线性的额外空间O(N^2)时间复杂度

    2.2.12次线性的额外空间。用大小M将数组分为N/M块(简单起见,设M是N的约数)。实现一个归并方法,使之所需的额外空间减少到max(M,N/M):(i)可以先将一个块看做一个元素,将块的第一个元素作为块的主键,用选择排序将块排序;(ii)遍历数组,将第一块和第二块归并,完成后将第二块和第三块归并,等等。
    答:一个O(N^2)时间复杂度,O(M)空间复杂度的算法。
    1)将a划分成N/M个单个长度最长为M的子数组,对每个子数组使用归并排序算法排序。

    2)将a划分成N/M个单个长度最长为M子数组,以每个子数组的第一个元素作为排序关键字,使用选择排序算法将各个子数组排序。对N/M个子数组排序,在归并时会因归并的两段已有序而不用再归并。

    3)归并子数组1和子数组2,再归并子数组1~2和子数组3,再归并子数组1~3和子数组4,直到归并完子数组1~(N/M-1)和子数组N/M。例如下现的情况(2,20,30)(3,5,8)(4,6,10),归并前两个后为(2,3,5)(8,20,30)(4,6,10),此时若只归并后面两个子组数,归并后的结果是(2,3,5)(4,6,8)(10,20,30)此时是无序的。如果在子数组1,2归并后,再将1,2与子数组3归并,得到的结果(2,3,4)(5,6,8)(10,20,30)才有序,所以此种采用了后段与所有前段归并的方式,也因此形成O(N^2)时间复杂度,但也可以看成是O((N/M)^2)时间复杂度。

    4)如果归并的两段的交界值有序,那么跳过本次归并,无序时归并这两段。然后进行下一段与所有前段的归并。归并时先将后段长度为M的子数组复制到辅助数组aux,然后将前段和辅组数组进行归并,两段中的大值从数组a的右边归并到左边。
    图片

    public class E2d2d12
    {
        public static void sort(Comparable[] a,int M)
        {
           int N=a.length;
           Comparable[] aux=new Comparable[M];
           //sort each block elements, block size is 2*M
           for(int lo=0;lo<N;lo=lo+M)
               sort(a,aux,lo,lo+M-1);
           //sort all blocks with block first element
           SelectionSortBlock(a,M);
           //Merge
           for(int j=1;j<N/M;j++)
           {
               if (!less(a[j*M],a[j*M-1])) continue;
               Merge(a,aux,0,j*M-1,(j+1)*M-1);
           }
       }
       
        private static void sort(Comparable[] a,Comparable[] aux,int lo,int hi)
        {
            if (hi<=lo) return;
            int mid=lo+(hi-lo)/2;
            sort(a,aux,lo,mid);
            sort(a,aux,mid+1,hi);
            if (!less(a[mid+1],a[mid])) return;
            Merge(a,aux,lo,mid,hi);
        }
      
        //merge bigger value to the maxIndex of array a.
        private static void Merge(Comparable[] a,Comparable[] aux,int lo,int sp,int hi)
        {
            int M=hi-sp;
            //copy right half of array a to aux
            for(int i=0;i<M;i++)
                aux[i]=a[sp+1+i];
            //merge from array aux with left half  of a to  a
            int auxTop=M-1;
            int aTop=sp;
            for(int k=hi;k>=lo;k--)
            {
                if(auxTop<0) a[k]=a[aTop--];
                else if (aTop<lo) a[k]=aux[auxTop--];
                else if(less(aux[auxTop],a[aTop])) a[k]=a[aTop--];
                else a[k]=aux[auxTop--];
            }
        }
       
       private static void SelectionSortBlock(Comparable[] a,int M)
        {
            int length=a.length;
            int minIndex;
            for(int i=0;i<length;i=i+M)
            {
                minIndex=i;
                for(int j=i+M;j<length;j=j+M)
                   if(less(a[j],a[minIndex])) minIndex=j;
                exch(a,i,minIndex,M);     
             }       
        }

          
        private static boolean less(Comparable v,Comparable w)
        {
            return v.compareTo(w)<0;
        }
       
         private static void exch(Comparable[] a,int i,int j,int length)
        {
            Comparable t;
            for(int index=0;index<length;index++)
            {
                t=a[i+index];
                a[i+index]=a[j+index];
                a[j+index]=t;
            }
        }
       
         public static boolean isSorted(Comparable[] a)
        {
            int len=a.length;
            for(int i=1;i<len;i++)
                if (less(a[i],a[i-1])) return false;
            return true;
        }
           
        public static void main(String[] args)
        {
            int N=Integer.parseInt(args[0]);
            int M=Integer.parseInt(args[1]);
            Double[] a=new Double[N];
            for(int i=0;i<N;i++)
                a[i]=StdRandom.uniform();
            sort(a,M);
            StdOut.printf("isSorted=%s",isSorted(a));
        }
    }
    问题中的max(M,N/M)没有用到、将第一块和第二块归并,完成后将第二块和第三块归并等等没有用到,块排序对第一块和第二块,第二块对第三块的归并的意义有没有可能是将时间复杂度降底到O(NlgN)的一个前提保证?如果是应该怎么使用?很遗憾,但是下面的内容说明有更好的时间复杂度算法。 图片

  • 相关阅读:
    Jzoj4721 LCS
    Jzoj4721 LCS
    Bzoj3196 二逼平衡树
    Bzoj3196 二逼平衡树
    Jzoj4715 树上路径
    Jzoj4715 树上路径
    031下一个排列
    汉诺塔问题【递归】
    求全排列和组合问题
    030串联所有单词并匹配
  • 原文地址:https://www.cnblogs.com/longjin2018/p/9860095.html
Copyright © 2011-2022 走看看