zoukankan      html  css  js  c++  java
  • LeetCode152. 乘积最大子数组

    要求乘积最大的子数组(子数组一定都是连续的),可以暴力枚举子数组起点和终点,求和。但是肯定超时。

    如果用动态规划,则只需要一遍扫描就可以得出结果。

    可以用maxProduct[i]表示以i结尾的最大的子数组乘积。

    如果所有nums[i]都是正数,则maxProduct[i]就是max(nums[i], maxProduct[i - 1] * nums[i]),
    也就是当前数和以i - 1结尾的最大子数组乘积和当前数的乘积的较大值。

    但是在这题里,nums[i]有可能是负数,众所周知负负得正,所以有可能前面某个子数组的乘积非常的“负”且当前的nums[i]也是一个负数,
    以至于之前的那个负的子数组的积和nums[i]的乘积反而是最大的。

    因此我们不仅需要一个maxProduct数组记录以当前位置i结尾的最大子数组的积,还需要一个minProduct数组记录以当前位置i结尾的最小子数组的积。

    对于每一个maxProduct[i],它的值应该是nums[i], maxProduct[i - 1] * nums[i], minProduct[i - 1] * nums[i]三者中最大的,
    对于每一个minProduct[i],它的值是三者中最小的。

    我们只需要一遍扫描更新所有的maxProduct和minProduct。

    最终答案就是maxProduct数组中的最大值。

    代码如下:

    class Solution {
    public:
        int maxProduct(vector<int>& nums) {
            int size = nums.size();
            vector<int> maxProduct(size), minProduct(size);
            maxProduct[0] = nums[0], minProduct[0] = nums[0];
            for(int i = 1; i < size; ++i) {
                maxProduct[i] = max(nums[i], max(maxProduct[i - 1] * nums[i], minProduct[i - 1] * nums[i]));            //这一行和下一行对调位置也行,只要更新了maxProduct和minProduct就好
                minProduct[i] = min(nums[i], min(maxProduct[i - 1] * nums[i], minProduct[i - 1] * nums[i]));
            }
            return *max_element(maxProduct.begin(), maxProduct.end());
        }
    };
    
  • 相关阅读:
    LCA+链式前向星模板
    truffle编译合约常见问题及其在私链上的部署与交互
    RMQ入门解析
    最短路_搜索
    无向图边双联通分量+缩点
    有向图+强联通分量
    染色法判二分
    邻接表存图
    贪心算法
    贪心算法
  • 原文地址:https://www.cnblogs.com/linrj/p/13402469.html
Copyright © 2011-2022 走看看