Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4]
,
the contiguous subarray [4,−1,2,1]
has the largest sum = 6
.
这个题naive的方法,就是2次for循环,找出最大的值。 有没有更好的办法?
通过直觉,里面貌似有dp的身影:但最大的困惑就是,你不知道哪段是最大的,尤其是在一次遍历的情况下。
我们肯定是要定义一个全局变量,max,来找出这个数组里最大的和。但是,如何每次求出最大呢?这个max和谁比较好呢?
其实这就是一个局部最大和全局最大的问题。
简化下思维:就是舍弃连续的负数,维持一个局部的最大量max_local,全局最大max和局部最大max_local来比较,维持。
就以例子来说: -2,-3我们可以跳过,从4开始,一直加到5,sum=7.
这个过程肯定是特例,我们尝试下总结出generic的递推。
4,-1,-2,1,5相当于4被-1,-2消耗掉,还剩1,到了5,又重获新生。
那么相当于,到了4的时候,把局部最大记录下来,max=4。继续往前走,-1,-2,至少还是正的,如果直接给出一个-5,那么局部和就小于0了,我们完全可以跳过这段负数了。
现在有些思路了:其实就是当局部和为正,我们就继续往前加。局部和为了负,那就舍弃掉前面的和,重新开始算。但是之前那部分的最大和我们已经求出来了。
下面是精简的代码
curr_max= Math.max(a[i],curr_max+a[i]) 这个其实就代表了:如果之前的连续最大和大于0,那我就加上,反之,就用a[i]最为最大和
下面一句暗含了,max_so_far肯定是大于这个数组中最小的数的
public int maxSubArraySum(int a[], int size)
{
int max_so_far = a[0];
int curr_max = a[0];
for (int i = 1; i < a.length; i++)
{
curr_max = Math.max(a[i], curr_max+a[i]);
max_so_far = Math.max(max_so_far, curr_max);
}
return max_so_far;
}