LeetCode152 乘积最大子数组

50 阅读1分钟

leetcode.cn/problems/ma…

image.png

解法一:自底向上的递推DP

比如 nums[i] = -1,nums[0..i-1] 子数组的最大元素乘积为 10,那么能不能就说 nums[0..i] 的最大元素乘积为 max(-1, -1 * 10) = -1 呢?

其实不行,因为可能nums[0..i-1] 子数组的最小元素乘积为 -6,那么 nums[0..i] 的最大元素乘积应该为 max(-1, -1 * 10, -1 * -6) = 6`。

func maxProduct(nums []int) int {
    // dp1[i]表示以nums[i]结尾的子数组的最小乘积
    dp1 := make([]int, len(nums))
    // dp2[i]表示以nums[i]结尾的子数组的最大乘积
    dp2 := make([]int, len(nums))
    // base case, 只有一个数可选
    dp1[0] = nums[0] 
    dp2[0] = nums[0]

    for i:=1; i<len(nums); i++{
        dp1[i] = min(
            nums[i], 
            min(dp1[i-1]*nums[i], dp2[i-1]*nums[i]), 
        )
        dp2[i] = max(
            // 只选择当前元素作为新的子数组
            nums[i],
            // 考虑到负负得正
            // 若nums[i]为负数,那么就要和前i-1个数的最小乘积相乘
            // 若nums[i]为整数,那么就要和前i-1个数的最大乘积相乘
            // 不管怎么样,把二者都算一下取较大值,就不用判断正负情况了
            max(dp1[i-1]*nums[i], dp2[i-1]*nums[i]),
        )
    }

    res := math.MinInt
    for _, v := range dp2{
        res = max(res, v)
    }
    return res
}

func min(a, b int) int{
    if a < b{
        return a
    }
    return b
}

func max(a, b int) int{
    if a > b{
        return a
    }
    return b
}