【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
相关推荐
星轨初途35 分钟前
LeetCode 热题 100——day2 字母异位词分组
c++·算法·leetcode
happyprince1 小时前
篇1:整体观 · bitsandbytes项目全貌解读
人工智能·算法
青梅橘子皮1 小时前
STL---map/set... “家族“详解(从使用到底层)(1)
数据结构·算法
让学习成为一种生活方式1 小时前
DNA 甲基化综述(模式、调控与功能)--Current Opinion in Plant Biology
算法
-森屿安年-2 小时前
647. 回文子串
c++·算法·动态规划
皓月斯语2 小时前
P5736 【深基7.例2】质数筛
c++·算法·题解
极序时代GEO品牌优化3 小时前
杭州极序时代|面向地域、设备与用户画像的动态GEO
人工智能·python·算法·极序时代geo
啦啦啦啦啦zzzz4 小时前
贪心算法和动态规划
c++·算法·贪心算法·动态规划
雪碧聊技术4 小时前
力扣 72. 编辑距离——动态规划经典例题
算法·leetcode·动态规划
happyprince4 小时前
篇3:bitsandbytes-深刻观-哲学与升华
人工智能·算法