最大连续子数组和
来源:互联网 发布:中投证券交易软件 编辑:程序博客网 时间:2024/05/18 17:27
问题描述:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和,求所有子数组的和的最大值。
分析:这个问题存在多种解法,各个解法的时间复杂度不一样,这里我列举三种解法。
解法一:暴力法,可以采用三重循环实现,第一重循环,记作子数组的开始数,第二种循环记作子数组的结尾数,第三重循环计算开始到结尾的和,并和目前最大和进行比较,更新最大和。
本质上就是穷举所有的子数组,然后求和。此方法的时间复杂度为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类中全部实现,分别对应三个方法,都是比较通用的代码,读者可以很容易转换为其他语言实现。
public class Maxsum { public static int fun1(int array[]){ //时间复杂度为O(n^3) int n=array.length; if(n<=0)return 0; //如果是空数组,直接返回0 int maxSum = array[0]; //最小和设为第一个数组元素的值 int currSum = 0; for (int i = 0; i < n; i++) //子数组起点 { for (int j = i; j < n; j++) //子数组终点 { for (int k = i; k <= j; k++) //子数组求和 { currSum += array[k]; } if (currSum > maxSum) //更新最大和 maxSum = currSum; currSum = 0; //每次用完清空 } } return maxSum; } public static int fun2(int array[]){ //时间复杂度为O(n) int n=array.length; if(n<=0)return 0; //如果是空数组,直接返回0 int currSum = 0; int maxSum = array[0]; for (int j = 0; j < n; j++) { currSum = (array[j] > currSum + array[j]) ? array[j] : currSum + array[j]; maxSum = (maxSum > currSum) ? maxSum : currSum; } return maxSum; } public static int fun3(int array[]){ //动态规划思想,时间复杂度为O(n) int n=array.length; if(n<=0)return 0; //如果是空数组,直接返回0 int f[]=new int[n]; f[0]=array[0]; int max=f[0]; for(int i=1;i<f.length;i++) {if(f[i-1]<=0 ||i==0)f[i]=array[i]; else f[i]=f[i-1]+array[i]; if(max<f[i])max=f[i]; } return max; }public static void main(String[] args) {// TODO 自动生成的方法存根 int a[]={1,-2,3,10,-4,7,2,-5}; System.out.print("数组为:"); for(int i=0;i<a.length;i++) System.out.print(a[i]+","); System.out.println(); System.out.println("暴力法求解答案为:"+fun1(a)); System.out.println("扫描法求解答案为:"+fun2(a)); System.out.println("动态规划求解答案为:"+fun3(a));}}
输出结果为:
数组为:1,-2,3,10,-4,7,2,-5,
暴力法求解答案为:18
扫描法求解答案为:18
动态规划求解答案为:18
- 连续子数组最大和
- 连续最大子数组和
- 连续子数组最大和
- 最大连续子数组和
- 连续子数组最大和
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和。
- 最大子数组和(连续)
- 最大连续子数组和
- 最大连续子数组和
- 最大连续子数组和
- [IMX6DL]超声波模块KS103 Linux驱动源代码
- 【问题解决】Maven搭建Web项目中org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问
- hdu 5660 暴力枚举
- iOS常见问题
- SVN命令使用
- 最大连续子数组和
- Activity(一)—生命周期及启动模式
- maven的入门与测试
- 客户端-服务器模式(架构)
- postgres函数和操作符
- 今日BBC
- SourceTree名词解释
- 更多C#网络学习资料
- nginx 编译详细参数