【动态规划】——最大子序和

今天总结一下有关动态规划问题中最大子序和的问题。

53.最大子数组和

题目要求给定一个数组,让我们求出最大连续子数组的和。我们使用动态规划来解决此类问题。

dp[i]表示以nums[i]结尾的连续子序列的和的最大值。那么我们要求的答案就是max{dp[i]}.其状态转移方程很容易就看出为dp[i]=max(dp[i],dp[i]+dp[i-1])。因为dp[i]需要尽可能的大,所以当dp[i-1]+dp[i]大于dp[i]时,我们更新dp[i]的值。代码如下:

class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n=nums.size();
vector<int> dp(nums);
dp[0]=nums[0];
for(int i=1;i<n;i++){
dp[i]=max(dp[i],dp[i]+dp[i-1]);
}
int ans=*max_element(dp.begin(),dp.end());
return ans;
}
};

918.环形数组的最大和

这个题目题干给的很复杂,力扣官方的题解也不是写给人看的(至少我这种菜鸟完全看不懂写的什么天书)。但其实就是两种情况:

1、最大子数组和出现在数组内部:举个例子:

a1,a2,a3,(a4,...,ai,ai+1,ai+2,)...,an-1,an。其中a[4:i+2]就是我们所要求的和最大的子数组。这种情况与前面所述的最大子数组和问题一模一样。

2、最大子数组和出现在数组连接处:

(a1,a2,a3,a4),...,ai,ai+1,ai+2,...,(an-1,an),其中an-1,an,a1,a2,a3,a4即为我们所求。这个情况我们需要意识到一点:

数组和=最大子序列和+最小子序列和

上述式子其实很好理解:一个数组的和为Sn,其中最大的连续子序列和为An,由于数组为循环数组,首尾相接,剩下部分也是一个连续的子数组,这一部分的和Bn也就是整个数组的最小子序列和。因为如果Bn不是最小子序列和,那么从该子序列中还可以再分出一个子序列,这个子序列的和可以并入到最大的连续子序列和中。

理解到这一点,这题的代码就不难写出:

class Solution {
public:
int maxSubarraySumCircular(vector<int>& nums) {
int n=nums.size();
vector<int> fMin(nums),fMax(nums);
int sum=nums[0];
for(int i=1;i<n;i++){
fMin[i]=min(fMin[i],fMin[i]+fMin[i-1]);
fMax[i]=max(fMax[i],fMax[i]+fMax[i-1]);
sum+=nums[i];
}
int maxV=*max_element(fMax.begin(),fMax.end());
int minV=*min_element(fMin.begin(),fMin.end());
return max(maxV,sum-minV==0?maxV:sum-minV);
}
};

152.乘积最大子数组

本题要求我们求给定数组的最大连续子序列的积。

此题的想法与918有相似之处:都需要维护两个数组fMax和fMin,其中一个是最大子序列积,一个是最小子序列积。其中最小子序列积一定是负的。因为这个题中有负数的存在,其不满足动态规划问题要求的最优子结构问题,举个例子:

例如【-2,3,-4】中,-4的最优解不是3*(-4),而是(-2)3(-4),所以我们需要分正负来讨论,多维护一个数组fMin,用来记录乘积的最小值(通常为负),当当前数字为负值时,可以调用fMin中记录的值来获得结果。

class Solution {
public:
int maxProduct(vector<int>& nums) {
vector<int> fMax(nums),fMin(nums);
for(int i=1;i<nums.size();i++){
fMax[i]=max(fMax[i],max(fMax[i]*fMax[i-1],fMax[i]*fMin[i-1]));
fMin[i]=min(fMin[i],min(fMin[i]*fMin[i-1],fMin[i]*fMax[i-1]));
}
int ans=*max_element(fMax.begin(),fMax.end());
return ans;
}
};

 

posted @   天涯海角寻天涯  阅读(433)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
点击右上角即可分享
微信分享提示