152. 乘积最大子数组

题目描述

思路
我们使用一维动态规划来解决这道题。题目中给定了我们一个数组nums,并且其数值范围是在[-10, 10],重点需要关注的是可能会出现负数 。因此,我们需要维护两个数组,分别是mmax和mmin,来记录0...i位置的最大值和最小值。
我们先考虑最大值的情况。nums[0...i]的最大值,也就是mmax[i],有三种可能,要么就是nums[i]自身;要么是nums[i] * mmax[i - 1],也就是与上一个最大值累乘;要么就是nums[i] * mmin[i - 1],也就是nums[i]与0..<i的最小值累乘(比如mmin[i - 1]是一个很小的负数,而nums[i]恰好也是一个很小的负数「负数越小,其绝对值越大」,那么二者相乘,负负得正,得到的正数会很大)。取mmax[i] = max(nums[i], nums[i] * mmax[i - 1], nums[i] * mmin[i - 1])。
同时,对于最小值,维护的情况和mmax相同,只不过取mmin[i] = min(nums[i], nums[i] * mmax[i - 1], nums[i] * mmin[i - 1])。
基于此,最后通过slices.Max取mmax的最大值就是答案。
Golang 题解
go
func maxProduct(nums []int) int {
mmax, mmin := make([]int, len(nums)), make([]int, len(nums))
copy(mmax, nums)
copy(mmin, nums)
for i := 1; i < len(nums); i ++ {
mmax[i] = max(nums[i], nums[i] * mmax[i - 1], nums[i] * mmin[i - 1])
mmin[i] = min(nums[i], nums[i] * mmax[i - 1], nums[i] * mmin[i - 1])
}
return slices.Max(mmax)
}