题目:
给定一个数组,当中有正负数,求当中的一段“子数组”(即任意长度,连续的数字),使得这个“子数组”的和是所有“子数组”和中最大的,
如给定的数组为12, -8, 5, 66, -21, 0 ,35, -44,7,则最大的和的子数组为{12, -8, 5, 66, -21, 0 ,35},最大的和为89.
思路:
1.从第一个正数开始,从左往右依次相加元素,当累加的值不小于零时就继续加,如果小于零,则停下,记录此时的累加值以及开始的位置和结束的位置;
2.再接着从下一个正数开始,重复第一步,如果这一段的累加值大于第一次的,则替换之前保存的累加值以及用新的开始位置和结束位置来替换之前保存的开始位置和结束位置;
3.遍历完整个数组,得到的开始位置和结束位置就是最大子数组的开始位置和结束位置。
代码:
/**
* CopyRight,2010 by XingYaan
*/
package src;
/**
* 给定一个数组,当中有正负数,求当中的一段“子数组”(即任意长度,连续的数字),
* 使得这个“子数组”的和是所有“子数组”和中最大的,
* 如给定的数组为12, -8, 5, 66, -21, 0 ,35, -44,7,
* 则最大的和的子数组为{12, -8, 5, 66, -21, 0 ,35},最大的和为89.
*
* @author Alvin
*/
public class MaxSubAryDemo {
public static int[] getMaxSub(int[] origin) {
int start = 0;
int end = 0;
int tmpStart = 0;
int maxSum = 0;
int tmpMaxSum = 0;
int plusNumCnt = 0;
int[] subAry = null;
for (int i =0; i < origin.length; i++) {
// 是正数
if (origin[i] > 0) {
plusNumCnt++;
if (plusNumCnt == 1) {
tmpStart = i;
}
tmpMaxSum += origin[i];
if (tmpMaxSum > maxSum) {
maxSum = tmpMaxSum;
end = i;
if (plusNumCnt == 1) {
start = tmpStart;
}
}
// 是负数或零
} else {
if (plusNumCnt > 0) {
tmpMaxSum += origin[i];
if (tmpMaxSum < 0) {
tmpMaxSum = 0;
plusNumCnt = 0;
}
}
}
}
subAry = new int[end - start + 1];
for (int i = 0; i < subAry.length; i++) {
subAry[i] = origin[start + i];
}
return subAry;
}
public static void main(String[] args) {
// int[] maxSubAry = getMaxSub(new int[]{12, -8, 5, 66, -21, 0, 35, -44, 7});
int[] maxSubAry = getMaxSub(new int[]{7, -44, 35, 0, -21, 66, 5, -8, 12});
for (int i : maxSubAry) {
System.out.print(i + " ");
}
}
}