题目大意:
连续最大子段积
题目思路:
最大值只能产生在一个正数x一个正数,一个负数乘一个负数,所以维护两个值,一个区间最大值,一个最小值
其他的话:
在讨论这个问题之前,我先来说一说大一刚开学就学了的最简单的dp问题之一的【最大连续子序列】
先来看一个数组a{ -2, 11, -4, 13, -5, -2 },求连续子序列中和最大的那个
对于第i个数来说,dp[i]表示,以i结尾的序列最大的和为dp[i]
状态转移方程为dp[i] = max{ dp[i-1] + a[i], a[i] }
无论哪个序列和最大,我们都可以表示为以a[i]结尾的子序列
我们先设dp[0] = a[0]
那么对于每一个a[i]来说,它只有两个选择
1)作为上一个序列的结尾
2)以自己为新的开始,作自己的结尾
如果那么就比较情况1)和情况2)哪个更大了,所以就出现了上面的表达式max{ dp[i-1] + a[i], a[i] }
最后只要遍历dp[]就可以找出最大值,因为如第五行所说,最大值一定存在于dp[]之中
同理:
对于这道题来说,唯一的区别就是前面的负数在这道题的上下文中或许是有用的,而在上一道题里负数是我们所不喜欢的
又因为xxxxxx....(还没组织好语言。。。。。。。以后再填坑)反正就是最大值可能由一个最大正数乘一个正数得到,也可能由一个最小的负数乘一个负数得到
我们需要再维护一个dp_min[]来保存以a[i]结尾的最小值
class Solution {
public:
int maxProduct(vector<int>& nums) {
int dp_max[nums.size()];
int dp_min[nums.size()];
dp_max[] = dp_min[] = nums[];
for (int i = ; i < nums.size(); i++) {
dp_max[i] = max(max(dp_max[i-]*nums[i], nums[i]), dp_min[i-]*nums[i]);
dp_min[i] = min(min(dp_min[i-]*nums[i], nums[i]), dp_max[i-]*nums[i]);
}
int ans = dp_max[];
for(int i=;i<nums.size();i++) ans = max(ans, dp_max[i]);
return ans;
}
};