1.题目描述
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
提示:
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
2.理清思路
2.1 动态规划
将一个问题拆解成几个小问题,分别求出小问题的解,即可推出大问题的解,那么如何判定能否用动态规划解问题?答案是满足以下两个条件:
- 具有最优解(题目中出现最多,最少,最大,最…)。
- 可以将大问题拆解成几个小问题来求解。
2.2 如何设计动态规划
- 根据题意,假设大问题的最优解。
- 根据大问题的最优解,能够推测出小问题的最优解,从而找到通用表达式,即状态转移方程。
- 根据状态转移方程设计代码逻辑。
2.3 题解
- 题目中出现 “最大” ,因此具有最优解,假设f(i)为以第i个元素结尾的子数组的最大和。
- 那么f(i)应该如何计算?根据题意 “连续子数组” ,说明f(i) = f(i-1)+nums[i],依次类推,f(i-1) = f(i-1-1)+nums[i-1],f(i-1-1) = f(i-1-1-1)+nums[i-1-1]… , 大问题拆解成了若干小问题,最终大问题的解,即为f(i)中的最大值。
- 考虑 f(i) 与 f(i-1)的关系。如果f(i-1)+nums[i] <= nums[i],则f(i)取nums[i],表示以i结尾的连续子数组的最大值为nums[i],因为单独一个nums[i]也是子数组。如果f(i-1)+nums[i] > nums[i],则f(i)取f(i-1)+nums[i]。即:f(i) = MAX{f(i-1)+nums[i],nums[i]},{ i >= 0 && i < n} 。
- 经过前面的分析,最终大问题的解,即为f(i)中的最大值,因此需要用一个max标记出所有f(i)中的最大值,方便计算完所有f(i)后直接返回f(max)。
3. 代码实现
int maxSubArray(int* nums, int numsSize){
int f[numsSize+1];
int i = 0;
int max = 0;
if(nums == NULL)
{
return -101;
}
f[0] = nums[0];
for(i = 1; i < numsSize; i++)
{
if((f[i-1] + nums[i]) <= nums[i])
{
f[i] = nums[i];
}
else
{
f[i] = f[i-1] + nums[i];
}
if(f[max] < f[i])
{
max = i;
}
}
return f[max];
}