连续子数组的最大和
OJ地址:连续子数组的最大和
方法一: 递归
int getSum(vector<int> &arr, int k)
{
if(k == 0)
return arr[0];
return max(getSum(arr, k - 1) + arr[k], arr[k]);
}
int FindGreatestSumOfSubArray(vector<int> array) {
if(array.size() == 0)
return 0;
int sum = 0;
int max = array[0];
for(int i = 1; i < array.size(); i++)
{
sum = getSum(array, i);
if(sum > max)
max = sum;
}
return max;
}
方法二:动态规划
状态定义:dp[i]表示以i结尾的连续子数组的最大和。所以最终要求dp[n-1]
状态转移方程:dp[i] = max(array[i], dp[i-1]+array[i])
解释:如果当前元素为整数,并且dp[i-1]为负数,那么当然结果就是只选当前元素
技巧:这里为了统一代码的书写,定义dp[i]表示前i个元素的连续子数组的最大和,结尾元素为array[i-1]
int FindGreatestSumOfSubArray(vector<int> array) {
int sz = array.size();
if(sz == 0)
return 0;
vector<int> dp(sz, 1);
dp[0] = array[0];
int ret = array[0];
for(int i = 1; i < sz; i++)
{
dp[i] = max(array[i], dp[i - 1] + array[i]);
ret = max(dp[i], ret);
}
return ret;
}
方法三:空间复杂度O(1)解法
思想很简单,就是对下标为i的元素array[i],先试探的加上array[i], 如果和为负数,显然,以i结尾的元素对整个结果不作贡献。
具体过程:
初始化:维护一个变量tmp = 0
如果tmp+array[i] < 0, 说明以i结尾的不作贡献,重新赋值tmp = 0
否则更新tmp = tmp + array[i]
最后判断tmp是否等于0, 如果等于0, 说明数组都是负数,选取一个最大值为答案。
int FindGreatestSumOfSubArray(vector<int> array) {
int tmp = 0;
int ret = array[0];
for(int k : array)
{
if(tmp + k < 0)
{
tmp = 0;
}
else
{
tmp += k;
}
ret = max(ret, tmp);
}
if(tmp)
return ret;
return *max_element(array.begin(), array.end());
}