《剑指offer》刷题——【时间效率】面试题42:连续子数组的最大和(java实现)
一、题目描述
输入一个整型数组,数组里有正数也有负数。数组中的一个或者多个整数组成一个子数组。求所有
子数组的和的最大值。要求时间复杂度为O(n)
二、题目分析
方法一:枚举所有子数组求和O(n^2)
- 枚举数组的所有子数组,并求出它们的和
- 一个长度为n的数组,总共有n(n+1)/2个子数组
方法二:举例分析数组的规律
- 定义两个变量,一个存累加的子数组和,一个存最大的子数组和
- 若当前累加和为负,则抛弃之前连续元素,从下一个元素重新累加
- 若当前累加和比保存的最大子数组和要大,则将当前累加和赋给最大子数组和
- 注:需考虑无效输入(数组为空,数组长度小于等于0),此时让函数返回0,但为了区分子数组的和的最大值为0、无效输入,定义一个全局变量来标记是否输入无效
public class Solution {
boolean invalidInput = false;
public int FindGreatestSumOfSubArray(int[] array) {
if(array==null || array.length<=0){
invalidInput = true;
return 0;
}
int curSum = array[0];
int greatSum = array[0];
for(int i =1; i<array.length; i++){
if(curSum < 0){
curSum = array[i];
}
else{
curSum = curSum + array[i];
}
if(curSum > greatSum){
greatSum = curSum;
}
}
return greatSum;
}
}
方法三:动态规划
- 用f(i)表示以第i个数字结尾的子数组的最大和,需求出max[f(i)],其中0<=i<n
f(i)= array[i] i=0 或者 f(i-1)<=0
f(i)=f(i-1)+array[i] i 不等于0 并且 f(i-1)>0 - 当以第i-1个数字结尾的子数组中所有数字的和小于0时,如果把这个负数与第i个数累加,则得到的结果比第i个数字本身还要小,此时以第i个数结尾的子数组就是第i个数本身
- 当以第i-1个数字结尾的子数组中所有的和大于0,则与第i个数字累加就得到以第i个数结尾的子数组的和