连续子数组的最大和
方法一:举例分析数组的规律
例如数组{1,-2,3,10,-4,7,2,-5}
分析:循环遍历数组,初始累加和为0。第一步,和为1.第二步,和为-1;第三步,和小于0,如果用-1加上3,和为2,小于3.那么从第一个累加的和必然小于从3开始累加的和,因此放弃之前累加的和。从3从新开始,此时和为3。第四步,和为13;第五步,和为9,小于原来的和,因此将之前得到的和13保存下来,它有可能是最大值。第五步,和为16,大于13.将最大值替换为16.依次类推。
方法二:采用动态规划法
遍历数组中的元素,逐个修改数组中到大当前元素的最大子数组和。
采用公式:f(i) = max{a[i], f(i-1)+a[i]}
第一步:和为1,元素值为1;第二步:和为-1,元素值为-2,和大于当前值,故元素值修改为-1;第三步:和为2,小于当前值,故房钱前面的和,将和修改为当前元素值;第四步:和为12,元素值为10,将元素值修改为12。以此类推。
package com.wyl;
/**
* 求数组的子数组中最大的和
* @author wyl
*/
public class SubArrayMax {
/**
* 方法一:
* 分析数组的规律进行编码,使用中间变量保存当前最大子数组和的值
* @param array
* @return
*/
public int maxSubArray(int[] array){
if(array.length <= 0){
return 0;
}
int sum = 0;
int max = 0;
//遍历数组,直到第一个不为负数的数
for(int i=0;i<array.length;i++){
if(sum < 0){ //子数组之和小于当前值,代表当前值前面的子数组和要比从当前值开始加和要小
sum = array[i];
}else{ //加上当前值后的值比之前的值小,则保存当前和,有可能为最大值
sum += array[i];
}
if(sum > max){
max = sum;
}
}
return max;
}
/**
* 方法二:
* 使用动态规划法,求出逐个子元素的最小和
* f(i) = max{a[i], f(i-1)+a[i]}
* 需要修改数组中元素的值
* @param args
*/
public int maxSubArray1(int[] array){
int sum = 0;
for(int i=0;i<array.length;i++){
sum += array[i];
if(array[i] < sum){ //将当前值修改为当前子数组和的最大值
array[i] = sum;
}else{ //子数组之和小于当前值,抛弃之前的sum,将当前值赋给sum
sum = array[i];
}
}
int max = 0 ;
for (int a:array) {//得到数组中的最大值
System.out.println(a);
if(a > max){
max = a;
}
}
return max;
}
public static void main(String[] args) {
SubArrayMax subArrayMax = new SubArrayMax();
int[] array = {1,-2,3,10,-4,7,2,-5,-7,-16,22,13};
int max = subArrayMax.maxSubArray1(array);
System.out.println("数组的最大子数组和为:" + max);
}
}