zoukankan      html  css  js  c++  java
  • 连续最大字段和问题

    最大子段和问题描述

    给定由 n 个整数(可能为负整数)组成的序列a1,a2,a3...an,求该数列中连续子段和最大!

        例如:当(a1,a2,a3,a4,a5)=(-2,11,-4,13,-5,-2)时,最大字段和为 20 (11 + (-4) + 13);

           以下例子都是以int data[6] = {-2,11,-4,13,-5,-2};    int n = 6;

     初始化数组: 

        //初始化数组
        private static Integer[] array = {-2, 11, -4, 13, -5, -2};

    算法一:对所有满足0<=i<=j<=n的(i,j)整数对进行迭代,对每个整数对,程序都要计算array[i...j]的总和,并检验该总和是否大于迄今为止的最大总和

    这段代码简洁明了,便于理解,但是程序执行的速度很慢,时间复杂度为O(n^3)

      

      /**
         * 时间复杂度为 O(n^3)
         */
        public static Integer maxSum1() {
            int maxSum = 0;             //存储最大子段和
            int tempSum;                //临时存储最大子段和
            for (int i = 0; i < array.length - 1; i++) {
                for (int j = i; j < array.length; j++) {
                    tempSum = 0;
                    for (int k = i; k <= j; k++) {
                        tempSum += array[k];
                        if (tempSum > maxSum) {
                            maxSum = tempSum;
                        }
                    }
                }
            }
            return maxSum;
        }
    

      

    算法二:对于算法一有一个明显的缺点,大量的计算重复。大家可以注意到:

    这段代码简洁明了,便于理解,相比算法一程序执行的速度较快,时间复杂度为O(n^2)

      注意:array[i...j]的总和与前面计算出的总和(array[i...j-1])密切相关,只需要在其基础上累加即可,无需大量重复计算!

        /**
         * 时间复杂度为 O(n^2)
         */
        public static Integer maxSum2() {
            int maxSum = 0;             //存储最大子段和
            int tempSum;                //临时存储最大子段和
            for (int i = 0; i < array.length - 1; i++) {
                tempSum = 0;
                for (int j = i; j < array.length; j++) {
                    tempSum += array[j];
                    if (tempSum > maxSum) {
                        maxSum = tempSum;
                    }
                }
            }
            return maxSum;
        }
    

      

    算法三:可以采用分治算法求解,采用二分法进行二分,然后进行递归求解,分别求出左边连续子段和最大值,右边连续子段和最大值,以及左边和右边连续子段和最大值之和,三者进行比较,从中选择一个最大值进行返回!(这个值即就是当前划分的小区间中最大值)

      注意:这段代码不太便于理解,但是程序相对于算法二执行的速度快,时间复杂度为O(n*logn)

      

      /**
         * 采用分治算法
         * 时间复杂度为 O(n*logN)
         */
        public static Integer maxSum3(int left, int right) {
            int maxSum = 0;
            if (left == right) {    //递归结束条件
                if (array[left] > 0) {
                    maxSum = array[left];
                } else {
                    maxSum = 0;
                }
                return maxSum;
            }
    
            int mid = (left + right) / 2;
            int leftMaxSum = maxSum3(left, mid);             //递归求解左部分最大值
            int rightMaxSum = maxSum3(mid + 1, right);  //递归求解右部分最大值
    
            //求解左边最大值和右边最大值之和
            int leftMax = 0;        //记录左边最大值
            int leftMaxTemp = 0;    //记录左边最大值的临时变量
            for (int i = mid; i >= left; i--) {
                leftMaxTemp += array[i];
                if (leftMaxTemp > leftMax) {
                    leftMax = leftMaxTemp;   //左边最大值放在 leftMax
                }
            }
            int rightMax = 0;
            int rightMaxTemp = 0;
            for (int j = mid + 1; j <= right; j++) {
                rightMaxTemp += array[j];
                if (rightMaxTemp > rightMax) {
                    rightMax = rightMaxTemp;  //右边最大值放在 rightMax
                }
            }
            maxSum = leftMax + rightMax;//(左边最大值和右边最大值之和)计算第 3 种情况的最大子段和
            //比较(左边最大值)和(右边最大值)以及(两边最大值之和)进行比较,从中选择一个最大值返回
            if (maxSum < leftMaxSum) {
                maxSum = leftMaxSum;
            }
            if (maxSum < rightMaxSum) {
                maxSum = rightMaxSum;
            }
            return maxSum;
        }
    

      

    算法四:使用动态规划来求解 ,由data[]数组我们易知,当maxSumTemp > 0时,maxSumTemp = data[i] + maxSumTemp (越加越大),否则maxSumTemp = data[i](不然越加越小)

      这段代码便于理解,但是程序相对于算法三执行的速度最快,时间复杂度为O(n)

      

        /**
         * 时间复杂度为 O(n)
         */
        public static Integer maxSum4() {
            int maxSum = array[0];
            int maxSumTemp = array[0];  //初始化
    
            for (int i = 1; i < array.length; i++) {
                if (maxSumTemp > 0) {           //最大值临时变量只有大于零,才可能越加越大
                    maxSumTemp += array[i];
                } else {                        //最大值临时变量只有小于零,直接等于data[i],否则越加越小
                    maxSumTemp = array[i];
                }
                if (maxSumTemp > maxSum) {      //判断赋值
                    maxSum = maxSumTemp;
                }
            }
            return maxSum;
        }
    

      

    测试代码:

     public static void main(String[] args) {
    //        Integer maxSum = maxSum1();
    //        Integer maxSum = maxSum2();
    //        Integer maxSum = maxSum3(0, array.length - 1);
            Integer maxSum = maxSum4();
            System.out.println("maxSum = " + maxSum);
        }
    

      每天进步一点点,日记月累就会变成大牛!

  • 相关阅读:
    SQL中 decode()函数简介
    php中foreach()的用法
    swfuploadphp上传说明
    未知,等知道什么以后再改
    php上传文件处理
    smarty中的section和foreach
    asp.net 异常:"DataBinding: 'System.Data.DataRowView'
    自定义MembershipProvider配合Asp.net 2.0 Login控件(转的,忘记哪里的了)
    地理信息中各种坐标系区别和转换总结
    asp.net异常DataRowView The type or namespace name 'DataRowView' could not be found
  • 原文地址:https://www.cnblogs.com/blogtech/p/11116524.html
Copyright © 2011-2022 走看看