最近在面试中遇到了求解“连续子数组的最大和(以下简称最大和)”题,因为之前没有了解过,所以当时没答出来。不过,感觉这道题比较有意思,所以事后就考虑了一下。但是在网上查了一下,又用实际代码测了一下后,发现自己考虑的方法还是有问题的,因此这里就把后来学习到的解题思路写下来。
下面的解题思路,是使用了减治法进行分析,思路如下:
首先,假设已知前i个元素组成的数组a(i),它的最大和是maxSum,则再加一个元素a[i+1]后新的数组a(i+1)的最大和的可能情况如下:
1、a[i+1]<=0,则a(i+1)与a(i)的最大和相同,为maxSum;
2、a[i+1]>0,则a(i+1)的最大和又分为两种情况:
a、与a(i)的最大和相同,maxSum;
b、a(i)右侧子数组的和rightSum与元素a[i+1]的和。
那么,现在涉及到了两个需要保存的元素,maxSum和rightSum,maxSum是maxSum为上一maxSum和当前rightSum中的较大值,那么接下来就需要分析怎么计算rightSum的值了。那么rightSum是怎么得来的呢?我们依然以元素a[i+1]加入时分析。
当元素a[i+1]加入时,新的rightSum也分两种情况:
1、数组a(i)的rightSum>0,则新的数组a(i+1)的rightSum为rightSum+=a[i+1];
2、数组a(i)的rightSum<=0,则旧的rightSum舍弃,新的rightSum重新开始,为rightSum=a[i+1]。
因此,计算一个数组a(n)的最大和,就可以根据数组a(n-1)的最大和、右侧子数组和以及元素a[n]来确定,如此类推,直到根据数组a(1)的最大和、右侧子数组和以及元素a[2]来确定数组a(2)的最大和,这样就很容易确定了。
实现代码如下:
package com.qing.algorithm;
import java.util.Random;
public class MaxSumOfContinuousSubArray {
public static void main(String[] args) {
int count = 100;
int bound = 200;
int[] a = new int[count];
Random random = new Random();
for (int i = 0; i < count; i++) {
a[i] = random.nextInt(bound) - bound / 2;
}
// a = new int[]{-3, 5, 14, -11, 9, 18, 22, -13, 25};
System.out.println(maxOf(a));
}
public static int maxOf(int[] a) {
int len;
if (a == null || (len = a.length) == 0) {//异常情况处理
throw new IllegalArgumentException("arr should has at least on item.");
}
if (len == 1) {
return a[0];
}
int maxSum = a[0], rightSum = a[0]; //初始化maxSum和rightSum
for (int i = 1; i < len; i++) {
if (rightSum > 0) {//旧的rightSum为正,则新的rightSum为旧的rightSum与新元素的和
rightSum += a[i];
} else { //否则,旧的rightSum舍弃,重新开始计算rightSum
rightSum = a[i];
}
if (rightSum > maxSum) {//若rightSum大于原来的maxSum,则将其赋值给新的maxSum
maxSum = rightSum;
}
}
return maxSum;
}
}