【LeetCode】152、乘积最大子数组

【LeetCode】152、乘积最大子数组

文章目录

一、dp

1.1 dp

从前向后遍历, 当遍历到 nums[i] 时, 有如下三种情况 能得到最大值:

  1. 只使用 nums[i], 例如 [0.1, 0.3, 0.2, 100] 则 [100] 是最大值
  2. 使用 max(nums[0...i-1]) * nums[i], 例如 [1, 3, 2, 100], 则 [1, 3, 2, 100] 是最大值, 因为 nums[0...i-1] 的 [1, 3, 2] 是最大值
  3. 使用 min(nums[0...i-1]) * nums[i], 例如 [-1, 3, -2, -100], 则 [-1, 3, -2, -100] 是最大值, 因为 nums[0...i-1] 的 [-1, 3, -2] 是最小值, 最小值乘以最小值得到最大值

所以, 每一步, 都取上述三种情况的最小值和最大值. 逐步向后递推.

go 复制代码
// go
func maxProduct(nums []int) int {
    ans := nums[0]
    mi, ma := nums[0], nums[0] // 初始值
    var curmin, curmax int // 临时值, 提前申请, 避免重复申请
    for i := 1; i < len(nums); i++ {
        v := nums[i]
        curmin = min(v, min(ma*v, mi*v))
        curmax = max(v, max(ma*v, mi*v))
        mi, ma = curmin, curmax
        ans = max(ans, ma)
    }
    return ans
}

算法讲解071【必备】子数组最大累加和问题与扩展-下

参考

关于「无后效性」

  • 某个阶段的状态一旦确定了,那么此后的过程不再受之前曾经的状态和决策的影响
  • 不管你过去经历过什么状态,做过什么决策,未来和过去无关
  • 当前的状态是此前历史的一个综合给出的结果,历史影响你也只是造就了你当前的状态,通过当前状态去影响你未来的进程

1.2 简化代码

为了简化代码, 可以不从1开始遍历

通过设置 mi, ma 为 1, 1, 即可从0开始遍历了
参考

go 复制代码
func maxProduct(nums []int) int {
    ans := nums[0]
    mi, ma := 1, 1
    var curmi, curma int
    for _, v := range nums {
        curmi = min(v, mi*v, ma*v)
        curma = max(v, mi*v, ma*v)
        mi, ma = curmi, curma
        ans = max(ans, ma)
    }
    return ans
}

二、多语言解法

C p p / G o / P y t h o n / R u s t / J s / T s Cpp/Go/Python/Rust/Js/Ts Cpp/Go/Python/Rust/Js/Ts

cpp 复制代码
// cpp
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int ans = nums[0];
        int mi = 1, ma = 1;
        for (int v : nums) {
            int curmi = min({v, v*mi, v*ma});
            int curma = max({v, v*mi, v*ma});
            mi = curmi;
            ma = curma; // 注意 c++ mi, ma = curmi, curma 有问题
            /*
            `mi, ma = curmi, curma;` 在 C++ 中是有问题的。这是因为 C++ 不支持这种同时赋值的语法。C++ 中的逗号运算符不会像 Python 或 Golang 那样实现多重赋值;相反,它会依次执行每个表达式,并返回最后一个表达式的值。因此,`mi, ma = curmi, curma;` 实际上只会对 `ma` 进行赋值,而不是同时对 `mi` 和 `ma` 赋值。
            */
            ans = max(ans, ma);
        }
        return ans;
    }
};
go 复制代码
// go 同上
python 复制代码
# python
class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        ans = nums[0]
        mi, ma = 1, 1
        for v in nums:
            curmi = min(v, v*mi, v*ma)
            curma = max(v, v*mi, v*ma)
            mi, ma = curmi, curma
            ans = max(ans, ma)
        return ans
rust 复制代码
// rust
impl Solution {
    pub fn max_product(nums: Vec<i32>) -> i32 {
        let mut ans = nums[0];
        let mut mi = 1;
        let mut ma = 1;
        for v in nums {
            let curmi = v.min(v*mi).min(v*ma);
            let curma = v.max(v*mi).max(v*ma);
            mi = curmi;
            ma = curma;
            ans = ans.max(ma);
        }
        ans
    }
}
js 复制代码
// js
/**
 * @param {number[]} nums
 * @return {number}
 */
var maxProduct = function(nums) {
    let ans = nums[0];
    let mi = 1;
    let ma = 1;
    for (const v of nums) {
        let curmi = Math.min(v, v*mi, v*ma);
        let curma = Math.max(v, v*mi, v*ma);
        mi = curmi;
        ma = curma;
        ans = Math.max(ans, ma);
    }
    return ans;
};
ts 复制代码
// ts
相关推荐
李永奉23 分钟前
C语言-字符串(定义)、字符串函数(strlen、strcat、strcpy、strcmp、strlwr、strupr)
c语言·开发语言·算法
啊阿狸不会拉杆1 小时前
《Java 程序设计》核心知识点梳理与深入探究
java·开发语言·python·算法·php·intellij-idea
行然梦实1 小时前
世代距离(GD)和反转世代距离(IGD)详析
人工智能·算法·机器学习·数学建模
草莓熊Lotso1 小时前
【LeetCode刷题指南】--单值二叉树,相同的树
c语言·数据结构·算法·leetcode·刷题
Swaggy T2 小时前
自动驾驶控制算法——PID算法
人工智能·算法·机器学习·自动驾驶
2501_924879262 小时前
强反光干扰下漏检率↓79%!陌讯多模态融合算法在油罐车识别的边缘计算优化
人工智能·算法·计算机视觉·视觉检测·边缘计算
菜鸟555552 小时前
图论:SPFA算法
算法·图论
测试老哥3 小时前
如何写好测试用例?
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
XRZaaa3 小时前
C 多线程实现大文件固定大小分卷与 SHA256 哈希校验
算法·哈希算法