152. Maximum Product Subarray 以及 讨论【最大连续子序列】

题目大意:

    连续最大子段积

 

题目思路:

    最大值只能产生在一个正数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]结尾的最小值

 1 class Solution {
 2 public:
 3     int maxProduct(vector<int>& nums) {
 4         int dp_max[nums.size()];
 5         int dp_min[nums.size()];
 6         dp_max[0] = dp_min[0] = nums[0];
 7         for (int i = 1; i < nums.size(); i++) {
 8             dp_max[i] = max(max(dp_max[i-1]*nums[i], nums[i]), dp_min[i-1]*nums[i]);
 9             dp_min[i] = min(min(dp_min[i-1]*nums[i], nums[i]), dp_max[i-1]*nums[i]);
10         }
11         int ans = dp_max[0];
12         for(int i=1;i<nums.size();i++) ans = max(ans, dp_max[i]);
13         return ans;
14     }
15 };

 

posted @ 2018-01-20 20:38  swallowblank  阅读(150)  评论(0编辑  收藏  举报