题目描述:
输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,那么该数组中连续的最大的子数组为3, 10, -4, 7, 2,则输出为该子数组和最大值18。
输入的数组为 -2,-8,-7,-1,-10,那么该数组中最大的子数组为 -1,则输出的该子数组和的最大值为 -1。
思路参考:
用total记录累计值,maxSum记录和最大。
基于思想: 对于一个数A,若是A的左边累计数非负,那么加上A能使得值不小于A,认为累计值对整体和是有贡献的。
如果前几项累计值负数,则认为有害于总和,total记录当前值。
此时 若和大于maxSum 则用maxSum记录下来
public class Solution
{
public int FindGreatestSumOfSubArray(int[] array)
{
if(array.length == 1)//只有一个元素
return array[0];
else
{
int total = array[0];//不能设置为0,防止元素均为负数
int maxSum = array[0];
for(int i=1; i<array.length; i++)
{
if(total >= 0)
total += array[i];
else
total = array[i];//否则,total记录当前值
if(total > maxSum)
maxSum = total;
}
return maxSum;
}
}
}
参考思路2:动态规划
用F(i)表示以array[i]为末尾元素的连续子数组和的最大值,则F(i) =max( F(i-1) + array[i], array[i] )
result:所有子数组的和的最大值,result=max(result,F(i))
如数组[6, -3, -2, 7, -15, 1, 2, 2]
初始状态:
F(0)=6
res=6
i=1:
F(1)=max(F(0)-3,-3)=max(6-3,3)=3
res=max(F(1),res)=max(3,6)=6
i=2:
F(2)=max(F(1)-2,-2)=max(3-2,-2)=1
res=max(F(2),res)=max(1,6)=6
i=3:
F(3)=max(F(2)+7,7)=max(1+7,7)=8
res=max(F(2),res)=max(8,6)=8
i=4:
F(4)=max(F(3)-15,-15)=max(8-15,-15)=-7
res=max(F(4),res)=max(-7,8)=8
以此类推
最终res的值为8
public class Solution
{
public int FindGreatestSumOfSubArray(int[] array)
{
int result = Integer.MIN_VALUE;
int maxValue = array[0];
for(int i=1; i<array.length; i++)
{
maxValue = Math.max(maxValue + array[i], array[i]);
result = Math.max(result, maxValue);
}
return result;
}
}
若想自己编写测试用例:
int ArrayLength = 8;//数组大小
int [] arr = new int [ArrayLength];
//Scanner 输入数组并读取的方法输入
Scanner sc = new Scanner(System.in);
for(int i = 0; i < arr.length; i++)
{
arr[i] = sc.nextInt();
}