2.分而治之

来源:互联网 发布:英伟达experience优化 编辑:程序博客网 时间:2024/06/07 06:25
   算法设计方法之一——分而治之,模仿了法国皇帝拿破仑在1852年12月2日奥斯特里茨战役中采用的接触策略。   分而治之(divide-and-conquer)将问题的一个实例划分为两个或更多个较小的实例,一直持续划分实例指导规模小到可以轻松获得答案为止。是一种自顶向下的方法。

1. 二分查找

/**     * 二分查找     * 基于非递减的有序数组     * @param s 非递减数组,查找区域     * @param x 查找值     * @return 返回查找值所在位置,如查找不到返回-1     */    public int binsearch(int[] s,int x){        int location =-1;        int start = 0;        int end = s.length-1;        int mid;        while(location==-1 && start<=end){            mid = (start+end)/2;            if(s[mid]==x){                location =mid;            }else if(s[mid]< x){                start = mid+1;            }else{                end = mid-1;            }        }        return location;    }

2. 合并排序

   两路合并(two-way merging),表示将两个有序数组合并为一个有序数组。合并排序即重复应用两路合并完成对数组的排序。
**此代码有错,还未调试成功,希望有大神可以提供意见**  /**    * 合并排序    * 将n个建排列为非递减序列    * @param S 排序后的有序数组cun'fan'f    */    static int S[] = {};    /**      * 两路合并      * 将两个有序数组合并为一个有序数组      **/    public void merge(int[] arr1,int[] arr2 ){        int i=0,j=0,k=S.length;        Arrays.copyOf(S,k+arr1.length+arr2.length);        while(i<arr1.length && j<arr2.length){            if(arr1[i]<arr2[j]){                S[k]=arr1[i];                i++;            }else{                S[k]=arr2[j];                j++;            }            k++;        }        if(i<arr1.length){            System.arraycopy(S,k,arr1,arr1[i],arr1.length-i);        }        if(j<arr1.length){            System.arraycopy(S,k,arr2,arr2[j],arr2.length-j);        }    }    /**     * 分而治之方法,拆分要排序的数组     * 调用merge()方法,两辆排序     * @param args 要排序的数组     */    public void mergesort(int[] arr){        int len = arr.length;        int [] left;        int [] right;        int devide;        if(len>1){            devide = len/2;            left = new int[devide];            System.arraycopy(arr,0,left,0,devide);            right = new int[len-devide];            System.arraycopy(arr,devide,right,0,right.length);            mergesort(left);            mergesort(right);            merge(left,right);        }    }

3. 快速排序

/**     * 快速排序     * @param arr 要排序的数组     * @param start 数组起始下标     * @param end 数组结束下标     */    public void quicksort(int[] arr,int start,int end){        /**         * 首先判断该数组长度是否大于1         */        if(start<end){            int i=start;            int j=end;            /**             * 以起始值为基准,并且该位置即为一个坑             */            int x=arr[start];            while(i<j){                /**                 * 从倒序分别与基准值x比对,大于基准值则比对下一项                 */                while(i<j && arr[j]>=x){                    j--;                }                /**                 * 直至该项值小于基准值,将该值放入正序的第一个坑,并且此位置空出来成为了一个坑                 */                if(i<j){                    arr[i++]=arr[j];                }                /**                 * 从正序开始分别与基准值比对,小于基准值则比对下一项                 */                while(i<j && arr[i]<=x){                    i++;                }                /**                 * 直至该项值大于基准值,将该值放入刚刚腾出来的坑,并且此位置空处理啊成为了一个坑                 */                if(i<j){                    arr[j--]=arr[i];                }            }            /**             * 将基准值x放入最后空出来的一个坑             * 经过上面排序之后,该基准值x左边都是小于该值的项,右边都是大于该值的项             */            arr[i]=x;            quicksort(arr,start,i-1);            quicksort(arr,i+1,end);            for(int l=0;l<arr.length;l++){                System.out.print(arr[l]+"  ");            }            System.out.println();        }    }

4. Strassen矩阵乘法算法

   1969年,Strassen发表了一种算法,对于矩阵的计算,无论是乘法或者加减法,其时间复杂度都优于根据矩阵的定义去计算。

5. 大整数的算数运算

   大整数,是指超出计算机硬件所能表示的整数范围。如果需要表示这样的大整数,就只能通过软件来表示和处理这些整数。
  • 大整数的加减法及其他线性时间运算
    可以使用一个整数数组来表示大整数,每个位置存储一个数位。例如:534127的存储,存储到数组S中
    S[6]
    S[5] |S[4]| S[3]| S[2]| S[1]| S[0]
    —-|—–|——|—–|—–|—–
    5 |3 |4 |1 |2 |7
    线性运算:
    u10m
    u/10m
    umod10m
    例如:534127=534103+127
  • 大整数的乘法
    567832=567103+832
    9423723=9423103+723
    按照分而治之的思想,一个n位的大整数u,可以表示为:
    u=x10(n/2)+y
    y(n/2)
    x(nn/2)
    两个整数相乘:
    u=x10m+y
    z=w10m+z
    uz=(x10m+y)(w10m+z)=xw102m+(xz+yw)10m+yz

该代码还待修正

/**     * 大整数乘法     * @param u 整数1     * @param v 整数2     */    public int prod(int u,int v){        int x,y,w,z;        int n = 6,m;        if(u==0||v==0){            return 0;        }        else{            m =n/2;            int pow = (int)Math.pow(10,m);            x=u/pow;            y=u%pow;            w=v/pow;            z=v%pow;            return x*w*(int)Math.pow(10,2*m)+(x*z+y*w)*pow+y*z;        }    }

6. 确定阈(yu)值

最优阈值:n
递归需要消耗大量的计算机内存,例如Strassen矩阵算法中,当矩阵为一阶矩阵时,直接按矩阵定义计算乘积反而比调用分而治之发效率高,类似于这样,求最优阈值n,当n大于该阈值时调用某个方法,当n小于阈值时调用另一效率更高的方法,这样可以使运算效率更快。

原创粉丝点击