题目:
输入一个整型数组,数组里有正数也有负数,数组中一个或连续多个整数组成一个子数组,求所有子数组的和的最大值。要求时间复杂度为O(n)
思路:
1、数组累加
从头到尾逐个累加数组中的每个数字,当累加之和小于0时,从下一个元素开始累加,并通过一个变量保存最大和。
2、动态规划,循环
思路与1一样,假设f(i)为以第i个数字结尾的子数组的最大和,那么
f(i)=A[i], f(i-1)<=0
f(i)=f(i-1)+A[i],f(i-1)>0
初始状态:f(0)=A[0]
最后求max(f(i)).
3. 动态规划,递归
可以推出转态转移方程式:
a[j]=Max(a[j],a[j-1]+a[j])
a[j]表示的是前j项的最大和,只需要取当前元素和前j-1项的加上当前元素的较大的值即可。
代码:
package array;
public class Offer31 {
private static boolean invalidInput = false;
//方法1,数字累加
public int findGreatestSumOfSubArray(int [] array){
if(array == null || array.length <=0){
invalidInput = true;
return 0;
}
invalidInput = false;
int maxSum = array[0];//最大的子数组和
int curSum = array[0];//累加的子数组和
for(int i = 1;i<array.length;i++){
if(curSum<=0)
curSum = array[i];
else
curSum += array[i];
if(curSum>maxSum)
maxSum = curSum;
}
return maxSum;
}
//方法2,动态规划
public int findGreatestSumOfSubArray_2(int [] array){
if(array == null || array.length <=0){
invalidInput = true;
return 0;
}
invalidInput = false;
int [] curSum = new int[array.length];
int maxSum = Integer.MIN_VALUE;//0x80000000
curSum[0] = array[0];
for(int i = 1;i<array.length;i++){
if(curSum[i-1] <=0 )
curSum[i] = array[i];
else
curSum[i] = curSum[i-1] + array[i];
if(curSum[i]<curSum[0])
curSum[i] = curSum[0];//对应测试案例数组全是负数,并且是这种{-1,-2,-3,-4,-5}没这句,输出-2
if(curSum[i] >maxSum)
maxSum = curSum[i];
}
return maxSum;
}
//方法3,递归
public int findGreatestSumOfSubArray_3(int [] array){
if(array == null || array.length <=0){
invalidInput = true;
return 0;
}
invalidInput = false;
int max = Integer.MIN_VALUE;
int sum = 0;
for(int i = 0;i<array.length;i++){
sum = Math.max(array[i], array[i]+sum);
max = Math.max(sum, max);
}
return max;
}
public static void main(String[] args) {
Offer31 of31 = new Offer31();
//功能测试,1,输入的数组有正数也有负数
int [] arr11 = {1,-2,3,10,-4,7,2,-5};
//System.out.println(of31.findGreatestSumOfSubArray(arr11));
//System.out.println(of31.findGreatestSumOfSubArray_2(arr11));
System.out.println(of31.findGreatestSumOfSubArray_3(arr11));
//功能测试,2,输入的数组全是正数
int [] arr21 = {1,2,3,4,5};
//System.out.println(of31.findGreatestSumOfSubArray(arr21));
//System.out.println(of31.findGreatestSumOfSubArray_2(arr21));
System.out.println(of31.findGreatestSumOfSubArray_3(arr21));
//功能测试,3,输入的数组全是负数
int [] arr31 = {-1,-2,-3,-4,-5};
//System.out.println(of31.findGreatestSumOfSubArray(arr31));
//System.out.println(of31.findGreatestSumOfSubArray_2(arr31));
System.out.println(of31.findGreatestSumOfSubArray_3(arr31));
//特殊输入测试,4,表述数组的指针为NULL
int [] arr41 = null;
//System.out.println(of31.findGreatestSumOfSubArray(arr41));
//System.out.println(of31.findGreatestSumOfSubArray_2(arr41));
System.out.println(of31.findGreatestSumOfSubArray_3(arr41));
}
}
运行结果:
18
15
-1
0