152、乘积最大子序列

  1. 152、乘积最大的子序列
    1. 示例 1:
    2. 示例 2:
  • 题解
    1. 1、动态规划
  • 152、乘积最大的子序列

    给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

    示例 1:

    输入: [2,3,-2,4]
    输出: 6
    解释: 子数组 [2,3] 有最大乘积 6。
    

    示例 2:

    输入: [-2,0,-1]
    输出: 0
    解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
    

    链接:https://leetcode-cn.com/problems/maximum-product-subarray

    题解

    • 动态规划
      • dpMax[i] 表示以第 i 个元素的结尾的子数组,乘积最大的值,也就是这个数组必须包含第 i 个元素。
      • dpMax[i] 表示以第 i 个元素的结尾的子数组,乘积最小的值,也就是这个数组必须包含第 i 个元素。
      • 空间复杂度优化
        • 注意到更新 dp[i] 的时候,我们只用到 dp[i-1] 的信息,再之前的信息就用不到了。所以我们完全不需要一个数组,只需要一个变量去重复覆盖更新即可。

    1、动态规划

    public int maxProduct(int[] nums) {
        int n = nums.length;
        if (n == 0) {// 边界处理
            return 0;
        }
    
        int[] dpMax = new int[n];
        dpMax[0] = nums[0];
        int[] dpMin = new int[n];
        dpMin[0] = nums[0];
        int max = nums[0];
        for (int i = 0;i < n;i++) {
            // Math.max 和 Math.min函数是很好的择优工具函数而不用if else 去写
            dpMax[i] = Math.max(dpMin[i - 1]*nums[i],Math.max(dpMax[i - 1]*nums[i],nums[i]));
            dpMin[i] = Math.min(dpMin[i - 1]*nums[i],Math.min(dpMax[i - 1]*nums[i],nums[i]));
            max = Math.max(max,dpMax[i]);
        }
        return max;
    }
    
    // 空间优化
    public int maxProduct(int[] nums) {
        int n = nums.length;
        if (n == 0) {
            return 0;
        }
        int dpMax = nums[0];
        int dpMin = nums[0];
        int max = nums[0];
        for (int i = 1;i < n;i++) {
            int preMax = dpMax;
            dpMax = Math.max(dpMin*nums[i],Math.max(dpMax*nums[i],nums[i]));
            dpMin = Math.min(dpMin*nums[i],Math.min(preMax*nums[i],nums[i]));
            max = Math.max(max,dpMax);
        }
        return max;
    }
    
    • 两趟扫描
    public int maxProduct(int[] nums) {
        int max=nums[0];
        int res=1;
        // 顺序扫最大,累乘,遇0变1
        for(int num:nums){
            res=res*num;
            if(max<res)max=res;
            if(num==0)res=1;
        }
        // 逆序扫最大,累乘,遇0变1
        res=1;
        for(int i=nums.length-1;i>=0;i--){
            res=res*nums[i];
            if(max<res)max=res;
            if(nums[i]==0)res=1;
        }
        return max;
    }
    

    转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

    💰

    Title:152、乘积最大子序列

    Count:556

    Author:攀登

    Created At:2020-07-26, 00:19:44

    Updated At:2024-06-15, 15:52:32

    Url:http://jiafeimao-gjf.github.io/2020/07/26/152%E3%80%81%E4%B9%98%E7%A7%AF%E6%9C%80%E5%A4%A7%E5%AD%90%E5%BA%8F%E5%88%97/

    Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

    ×

    Help us with donation