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

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

文章目录

一、dp

1.1 dp

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

  1. 只使用 numsi, 例如 0.1, 0.3, 0.2, 100100 是最大值
  2. 使用 max(nums0...i-1) * numsi, 例如 1, 3, 2, 100, 则 1, 3, 2, 100 是最大值, 因为 nums0...i-11, 3, 2 是最大值
  3. 使用 min(nums0...i-1) * numsi, 例如 -1, 3, -2, -100, 则 -1, 3, -2, -100 是最大值, 因为 nums0...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
相关推荐
lhjcsubupt5 分钟前
第二十二篇 从随机过程到IMU噪声模型
算法·机器学习·概率论
神仙别闹19 分钟前
基于C语言处理机调度算法的实现
服务器·c语言·算法
Brilliantwxx19 分钟前
【算法从零到千】【16-23】 二分算法
数据结构·算法
8Qi86 小时前
回文子串(Palindromic Substrings)—— 题解
算法·leetcode·职场和发展·动态规划
小宋加油啊11 小时前
机械臂抓取物体 PVN3D算法调研学习
学习·算法·3d
lqqjuly11 小时前
前沿算法深度解析(一)
算法
小欣加油11 小时前
leetcode1926 迷宫中离入口最近的出口
数据结构·c++·算法·leetcode·职场和发展
happymaker062614 小时前
LeetCodeHot100——42.接雨水
算法
阿正的梦工坊14 小时前
【Rust】07-错误处理:Option、Result 与 ? 运算符
开发语言·算法·rust