• 最大连续子数组和


    问题描述:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和,求所有子数组的和的最大值。

    分析:这个问题存在多种解法,各个解法的时间复杂度不一样,这里我列举三种解法。

             解法一:暴力法,可以采用三重循环实现,第一重循环,记作子数组的开始数,第二种循环记作子数组的结尾数,第三重循环计算开始到结尾的和,并和目前最大和进行比较,更新最大和。

                        本质上就是穷举所有的子数组,然后求和。此方法的时间复杂度为O(n^3)。

                        对应下面代码的fun1()方法。

             解法二:对解法一进行优化,当我们求出当前子数组和和时,对于下一个数,如果将其放入子数组中,总和变大了,则直接将该数加入子数组中,否则将这个数作为新的子数组的开始数,依次类推。

                        这种方法的时间复杂度为O(n).

                        对应下面代码的fun2()方法。

             解法三:利用动态规划求解,关于什么是动态规划,这里不再解释,读者可以查阅其他相关资料。

                        我们可以设计一个函数,比如为f(i)表示以第个数字结尾的子数组的最大和,那么我们只要求出f(i)的最大值即可。可以列出以下公式:

                        当 i=0  或者f(i-1)<=0           f(i)=array[i]

                        当 i<>0并且 f(i-1)>0            f(i)=f(i-1)+array[i]

                       再解释下这个公式:当以第i-1个数字结尾的子数组中所有的数字的和小于等于0时,无论第i个数是什么,将他累加到子数组中,得到的结果肯定比他本身小。这时直接将这个数赋值给f(i)即可。

                                                如果以第i-1个数字结尾的子数组中所有的数字的和大于0时,与第i个数累加就得到了以第i个数结尾的子数组中所有数字的和。

                       这种方法的时间复杂度为O(n).

                       对应下面代码的fun3()方法。

              我将三种解法在一个Java类中全部实现,分别对应三个方法,都是比较通用的代码,读者可以很容易转换为其他语言实现。

     1 public class Maxsum {
     2     public static int fun1(int array[]){     //时间复杂度为O(n^3)
     3         int n=array.length;
     4         if(n<=0)return 0;                    //如果是空数组,直接返回0
     5         int maxSum = array[0];               //最小和设为第一个数组元素的值
     6         int currSum = 0;
     7         for (int i = 0; i < n; i++)          //子数组起点
     8         {
     9             for (int j = i; j < n; j++)      //子数组终点
    10             {
    11                 for (int k = i; k <= j; k++)   //子数组求和
    12                 {
    13                     currSum += array[k];
    14                 }
    15                 if (currSum > maxSum)         //更新最大和
    16                     maxSum = currSum;
    17                 currSum = 0;                 //每次用完清空
    18             }
    19         }
    20         return maxSum;
    21     }
    22     
    23     public static int fun2(int array[]){     //时间复杂度为O(n)
    24         int n=array.length;
    25         if(n<=0)return 0;                    //如果是空数组,直接返回0
    26         int currSum = 0;
    27         int maxSum = array[0];       
    28         for (int j = 0; j < n; j++)
    29         {
    30             currSum = (array[j] > currSum + array[j]) ? array[j] : currSum + array[j];
    31             maxSum = (maxSum > currSum) ? maxSum : currSum;
    32         }
    33         return maxSum;
    34     }
    35     
    36     public static int fun3(int array[]){          //动态规划思想,时间复杂度为O(n)
    37         int n=array.length;
    38         if(n<=0)return 0;                    //如果是空数组,直接返回0
    39         int f[]=new int[n];
    40         f[0]=array[0];
    41         int max=f[0];
    42         for(int i=1;i<f.length;i++)
    43             {if(f[i-1]<=0 ||i==0)f[i]=array[i];
    44             else f[i]=f[i-1]+array[i];
    45             if(max<f[i])max=f[i];
    46             }
    47         return max;
    48     }
    49 
    50     public static void main(String[] args) {
    51         // TODO 自动生成的方法存根
    52         int a[]={1,-2,3,10,-4,7,2,-5};
    53         System.out.print("数组为:");
    54         for(int i=0;i<a.length;i++)
    55             System.out.print(a[i]+",");
    56         System.out.println();
    57         System.out.println("暴力法求解答案为:"+fun1(a));
    58         System.out.println("扫描法求解答案为:"+fun2(a));
    59         System.out.println("动态规划求解答案为:"+fun3(a));
    60     }
    61 
    62 }
    View Code

    输出结果为:

    数组为:1,-2,3,10,-4,7,2,-5,
    暴力法求解答案为:18
    扫描法求解答案为:18
    动态规划求解答案为:18

  • 相关阅读:
    mybatis-plus-generator 实践
    Mybatis-Plus使用全解
    DevExpress v18.2新版亮点——DevExtreme篇(四)
    DevExpress VCL Controls 2019发展路线图(No.2)
    【版本更新】开发工具DevExtreme发布v18.2.7|附下载
    DevExpress v18.2新版亮点——DevExtreme篇(三)
    独家!DevExpress VCL Controls 2019发展路线图(No.1)
    界面控件DevExpress发布v18.2.7,新版全新出发|附下载
    DevExpress v18.2新版亮点——DevExtreme篇(二)
    DevExpress WinForms使用教程:皮肤颜色和LookAndFeel
  • 原文地址:https://www.cnblogs.com/guozhenqiang/p/5431122.html
Copyright © 2020-2023  润新知