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

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

文章目录

一、dp

1.1 dp

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

  1. 只使用 numsi, 例如 0.1, 0.3, 0.2, 100 则 100 是最大值
  2. 使用 max(nums0...i-1) * numsi, 例如 1, 3, 2, 100, 则 1, 3, 2, 100 是最大值, 因为 nums0...i-1 的 1, 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
相关推荐
大侠归来1 小时前
C 语言 | 在函数中操作数组
c语言·c++·算法
怕浪猫6 小时前
GEO 优化到底是什么?AI时代内容创作者必须懂的新技能
算法·面试·github
朝朝辞暮i7 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
Evand J8 小时前
【MATLAB例程】三维RRT+APF避障路径规划与到达角(AOA)定位算法|三维路径优化与定位仿真例程
算法·matlab·路径规划·代码·定位·rrt·aoa
weixin_307779139 小时前
有限产能智能排产与动态重排智能体:从需求解构到技术实现
开发语言·人工智能·算法·架构
朝朝辞暮i9 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法
朝朝辞暮i10 小时前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
ychqsq10 小时前
207.炸酱面
经验分享·职场和发展
Godspeed Zhao10 小时前
现代智能雷达技术14——算法(0)
线性代数·算法·雷达
可乐ea10 小时前
Agent 模型分级升级路由:用置信度阈值把贵模型省下来
人工智能·算法·机器学习·结构化输出·置信度路由·模型升级路由·大模型成本优化