152. Maximum Product Subarray(动态规划)



Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product.

Example 1:

Input: [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.

Example 2:

Input: [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.



由于负数的存在,需要同时保存当前最大值和当前最小值,所以需要维护两个DP表,可以分别表示为dp_min和dp_max。所以即为dp_max里的最大值。

需要维护的当前最大值和当前最小值,都是在dp_min[i-1] * A[i],dp_max[i] * A[i],和A[i]这三者里面取一即可。有了这个只关乎最终状态,不关乎过程细节的结论,解题过程可以大大简化。

 

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        n = len(nums)
        dp_max = nums.copy()
        dp_min = nums.copy()
        for i in range(1,n):
            dp_max[i] = max(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
            dp_min[i] = min(nums[i],dp_max[i-1]*nums[i],dp_min[i-1]*nums[i])
        return max(dp_max)

 

 

 

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

 

 

思考以上DP解法的空间开销过大的原因,是因为保存了整个DP表。其实整个过程中,获得dp[i]的值只需要dp[i-1]的值,所以是不需要保存整个DP表的。

这样一来,DP可以用滚动数组进行优化。简单的写法其实就是设一对prevMin/prevMax表示上一个值,以及还有一对curMin/curMax表示当前值。

 

 1 class Solution {
 2 public:
 3     int maxProduct(vector<int>& nums) {
 4         int n = nums.size();
 5         if(n==0) return 0;
 6         int dp_max_pre = nums[0];
 7         int dp_min_pre = nums[0];
 8         int dp_max;
 9         int dp_min;
10 
11         int res_val = nums[0];
12         for(int i =1;i<n;i++){
13             dp_max = std::max( std::max(dp_max_pre*nums[i],dp_min_pre*nums[i]),    nums[i]);
14             dp_min= std::min( std::min(dp_max_pre*nums[i],dp_min_pre*nums[i]),    nums[i]);
15             res_val =std::max(res_val,dp_max);
16             dp_max_pre = dp_max;
17             dp_min_pre = dp_min;
18         }
19          
20         return res_val;
21     
22     }
23 };

 

posted @ 2019-02-21 21:55  乐乐章  阅读(204)  评论(0编辑  收藏  举报