题目:
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.
但是理解其背后的原理却是比较困难的,我在代码的后面贴上了我对于解法原理的通俗演义,建议在看之前先看看第二种解法的出处
public static int maxSubArray1(int[] nums) {
int sum = 0;
int max = nums[0];
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (sum > max)
max = sum;
if (sum < 0)
sum = 0;
}
return max;
}
public int maxSubArray2(int[] A) {
if(A==null || A.length==0)
return 0;
int global = A[0];
int local = A[0];
for(int i=1;i<A.length;i++)
{
local = Math.max(A[i],local+A[i]);
global = Math.max(local,global);
}
return global;
}
背后原理:
当我们遍历到第i个数,对于前面的i-1个数必定会有一个连续的子集Q和最大,那么当到了第i个数时,最有可能挑战Q地位的肯定是包含第i个数的一个连续子集,因为若是在第i个数之前,连续子集的最大和是Q,那么从第一个数到第i-1个数这个集合中所有的可能的连续子集的和都被Q折服,被Q打败了,现在到了第i个数,出现了一个变量,如此一来,若有可能出现一个比Q更大的,那么这个连续的子集,必定是包含第i个数的一个子集。
对于第i个数来说,它要组建子集的队伍要打败Q,它就要审视在它之前的数对于它的队伍来说有没有增益,也就是说它们的和是否大于0,如果有增益的话就让队伍包括它们,否则就舍弃它们。
然后,就和Q决一死战。
但是对于我们的算法来说,为了降低时间复杂性,不能到了第i个数再去审视之前的数对于队伍的增益,而是要在到i之前就去审视。
这就是第一种解法中
if (sum < 0)
sum = 0;
的作用,sum是为第i个数准备的预备队,当发现这个预备队会对队伍有损害,即小于0时,就要坚决地舍弃,从头开始为第i个数组件队伍。
也是第二种解法
local = Math.max(A[i],local+A[i]);
的作用,看看是单独第i个数的力量大,还是加上前面的队伍力量大。