zoukankan      html  css  js  c++  java
  • 分治策略(算法)

    不积跬步无以至千里,不积小流无以成江海,程序人生的精彩需要坚持不懈地积累!

    分治策略

    在分治策略中我们递归的求解一个问题,在每层递归中应用如下三个步骤:
    分解:将问题划分成为一些子问题的形式,子问题形式与原问题一样,只是规模更小。
    解决:递归的求解子问题。如果问题的规模足够小,则停止递归,直接求解。
    合并:将子问题的解组合形成原问题的解。

    求解递归的O渐近界方法:

    【1】猜测代入法
    【2】递归树法
    【3】主方法 使用公式

    最大字数组和的求解

    package algorithm.java.ch04;
    
    /**
     * @author LbZhang
     * @version 创建时间:2015年12月21日 下午7:56:23
     * @description 最大子数组的和 问题是这样的:一个整数数组中的元素有正有负,在该数组中找出一个连续子数组,要求该子数组中各元素的和最大,
     *              这个子数组便被称作最大子数组。比如数组{2,4,-7,5,2,-1,2,-4,3}的最大子数组为{5,2,-1,2},
     *              最大子数组的和为5+2-1+2=8。
     */
    public class MaxSubArray {
        public static void main(String[] args) {
            int[] numArr = { 2, 4, -7, 5, 2, -1, 2, -4, 3 };
            System.out.println("暴力求解:");
            baoliHandle(numArr);
            System.out.println("线性求解:'");
            linarHandle(numArr);
            System.out.println("分治求解:");
            divHandle(numArr);
    
        }
    
        /*
         * 暴力求解办法
         */
        public static int baoliHandle(int[] arr) {
            int i, j;
            int len = arr.length;
            int maxSum = 0;
            int begin = 0, end = 0;
            for (i = 0; i < len; i++) {
                int Cursum = 0;// 每一个作为起点的累加的数据和的临时保存
                for (j = i; j < len; j++) {
                    Cursum += arr[j];
                    if (Cursum > maxSum) {
                        maxSum = Cursum;
                        begin = i;
                        end = j;
                    }
                }
    
            }
            System.out.println("最大字数组:");
            for (i = begin; i <= end; i++) {
                System.out.print(arr[i] + " ");
            }
            System.out.println();
            System.out.println("MaxSum: " + maxSum);
            return maxSum;
        }
    
        public static int divHandle(int[] arr) {
            SubArray sa = new SubArray();
            sa = findMaxSubArray(sa, arr, 0, arr.length - 1);
            System.out.println("最大字数组:");
            for (int i = sa.getBegin(); i <= sa.getEnd(); i++) {
                System.out.print(arr[i] + " ");
            }
            System.out.println();
            System.out.println("MaxSum: " + sa.getSum());
    
    
            return sa.getSum();
        }
    
        /**
         * 递归调用函数
         * 
         * @param sa
         * @param arr
         * @param i
         * @param j
         */
        private static SubArray findMaxSubArray(SubArray sa, int[] arr, int left,
                int right) {
            if (left == right) {
                sa.setBegin(left);
                sa.setEnd(right);
                sa.setSum(arr[left]);
                return sa;
            } else {
                int mid = (left + right) / 2;
                SubArray saleft = findMaxSubArray(sa, arr, left, mid);
                SubArray saright = findMaxSubArray(sa, arr, left, mid);
    
                SubArray sacross = findCrossingMaxSubArray(sa, arr, left, mid,
                        right);
    
                if (saleft.getSum() > saright.getSum()
                        && saleft.getSum() > sacross.getSum()) {
                    return saleft;
                } else if (saright.getSum() > saleft.getSum()
                        && saright.getSum() > sacross.getSum()) {
                    return saright;
                } else {
                    return sacross;
                }
            }
        }
    
        private static SubArray findCrossingMaxSubArray(SubArray sa, int[] arr,
                int left, int mid, int right) {
            int sum=0;
            int begin=0;
            int end=0;
    
            int leftsum = 0;
            for(int i=mid;i>=left;i--){
                sum=sum+arr[i];
                if(sum>leftsum){
                    leftsum=sum;
                    begin=i;
                }
            }
            int rightsum = 0;
            sum=0;
            for(int i=mid+1;i<=right;i++){
                sum=sum+arr[i];
                if(sum>rightsum){
                    rightsum=sum;
                    end=i;
                }
            }
    
            sa.setBegin(begin);
            sa.setEnd(end);
            sa.setSum(leftsum+rightsum);
    
            return sa;
        }
    
        /**
         * 最优方法,时间复杂度O(n)和最大的子序列的第一个元素肯定是正数因为元素有正有负,因此子序列的最大和一定大于0
         * 
         * @param arr
         * @return
         */
        public static int linarHandle(int[] arr) {
            int i;
            int len = arr.length;
            int maxSum = 0;
            int curSum = 0;
            int begin = 0, end = 0;
    
            for (i = 0; i < len; i++) {
                curSum += arr[i];
                if (curSum > maxSum) {
                    maxSum = curSum;
                    end = i;
                }
                // 如果累加和出现小于0的情况,
                // 则和最大的子序列肯定不可能包含前面的元素
                // 这时将累加和置0,从下个元素重新开始累加
                if (curSum < 0) {
                    curSum = 0;
                    begin = i + 1;// 最小从下一个开始
                }
            }
    
            System.out.println("最大字数组:");
            for (i = begin; i <= end; i++) {
                System.out.print(arr[i] + " ");
            }
            System.out.println();
            System.out.println("MaxSum: " + maxSum);
    
            return maxSum;
    
        }
    
    }
    

    运行结果:
    程序执行结果

    踏实 踏踏实实~
  • 相关阅读:
    android阅读器开发
    Android开源库
    Android开源项目分类汇总
    java 读取显示txt内容(Swing)
    Java 图形用户界面设计 (Swing)
    Java读取txt文件,换行写txt文件
    出国旅行口语必备300句
    100-days:nine
    100-days: eight
    The Attention Merchants
  • 原文地址:https://www.cnblogs.com/mrzhang123/p/5365818.html
Copyright © 2011-2022 走看看