给你一个整数数组nums,找出包含至少一个数字的连续子数组,要求它的和最大,返回它的和。
1. 常规思路
考虑每一个子数组的和的大小,在此基础上计算出和最大的数组。
// 考虑step为1到n的情况(超时)
public int maxSubArray(int[] nums)
{
int largestSum = 0;
// 先对数组nums的情况进行判断
if (nums == null || nums.length == 0)
{
return largestSum;
}
largestSum = nums[0]; // 将largestSum的值置为第一个元素的值
// 先计算出数组中的最大元素
for (int i=1; i<nums.length; i++)
{
if (nums[i] > largestSum)
{
largestSum = nums[i];
}
}
// 考虑步长为1到n的情况
for (int step=1; step < nums.length; step++)
{
for (int i=0; i+step< nums.length; i++)
{
largestSum = Math.max(largestSum, sum(nums, i, i+step));
}
}
return largestSum;
}
int sum(int[] nums, int start, int end)
{
int sum = 0;
for (int i=start; i<=end; i++)
sum += nums[i];
return sum;
}
2. 常规思路
从前向后迭代计算每一个子数组的和,取最大的值。
public int maxSubArray(int[] nums)
{
int largestSum = 0;
// 先对数组nums的情况进行判断
if (nums == null || nums.length == 0)
{
return largestSum;
}
int sum = 0;
largestSum = nums[0]; // 将largestSum的值置为第一个元素的值
// 先计算出数组中的最大元素
for (int i=1; i<nums.length; i++)
{
if (nums[i] > largestSum)
{
largestSum = nums[i];
}
}
for (int i=0; i<nums.length; i++)
{
sum = nums[i]; // sum每一轮的初值
for (int j=i+1; j<nums.length; j++)
{
sum += nums[j];
if (sum > largestSum)
{
largestSum = sum;
}
}
}
return largestSum;
}
3. 动态规划
当我们从前向后遍历数组时,对于数组中每一个整数,它只有两种选择:1)加入到之前的subArray;
2) 自己另起一个subArray。那什么时候会出现这两种情况呢?
如果之前的subArray的总体和大于0的话,我们认为其对后续的结果是有贡献的。这种情况下我们选择将其加入
之前的subArray中。如果之前的subArray的总体和为0或者小于0的话,我们认为其对后续的结果是没有贡献的,甚至
是有害的(小于0时)。这种情况下,我们选择以这个数字开始,另起一个subArray。
设状态为f [j], 表示以s[j]结尾的最大连续子序列和,则状态转移方程如下;
情况一,S[j] 不独立,与前面的某些数组成一个连续子序列,则最大连续子序列和为f [j-1] + S[j ]。
情况二,S[j]独立划分为一块,即连续子序列仅包含一个数S[j],则最大连续子序列和为S[j] 。
public int maxSubArray(int [] nums)
{
int curSum = nums[0];
int res = nums[0]; // 保存最终要返回的结果
for (int i=1; i<nums.length; i++)
{
curSum = Math.max(nums[i], nums[i] + curSum);
res = Math.max(res, curSum);
}
return res;
}