题目链接:https://leetcode.cn/problems/maximum-product-subarray/
/**
解法1: 贪心做法:
因为时乘积,由此得出以下结论
1、出现0,肯定分割为前后两个段,从这两个段内找乘积最大
2、在[2,-1,-3,-2,4]数组中,出现负数的个数为奇数时,将导致乘积为负数;
2.1 所以要将数组中的总乘积48, 除以从数组中的第一个负数位置开始从右往左的每个数;
2.2 所以要将数组中的总乘积48, 除以从数组中的最后一个负数位置开始从左往右的每个数;
2.3 从得到的两个结果中,判断是否为最大的乘积
3、在[2,-1,3,-2,4]数组中,出现负数的个数为偶数时,负负得正,就直接判断是否为最大乘积
解法2: 动态规划
转移方程:
minDp[i] = min(minDp[i-1]*nums[i], maxDp[i-1]*nums[i])
maxDp[i] = max(maxDp[i-1]*nums[i], minDp[i-1]*nums[i])
优化空间:滚动数组
//解法2: 代码
func maxProduct(nums []int) int {
maxF, minF, ans := nums[0], nums[0], nums[0]
for i := 1; i < len(nums); i++ {
mx, mn := maxF, minF
maxF = max(mx * nums[i], max(nums[i], mn * nums[i]))
minF = min(mn * nums[i], min(nums[i], mx * nums[i]))
ans = max(maxF, ans)
}
return ans
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
func min(x, y int) int {
if x < y {
return x
}
return y
}
*/
func maxProduct(nums []int) int {
nums = append(nums, 0)
fuNums := make([]int, 0)
product := 0
ans := nums[0]
left := 0
for i:=0; i<len(nums); i++ {
preP := product
if len(nums) - 1 != i {
if product == 0 {
product = nums[i]
} else {
product *= nums[i]
}
}
ans = max(product, ans)
// 遇到0 前面只需要算前面
if nums[i] == 0 {
// 如果这是最大乘积小于0,说明之前都是负数
if len(nums) - 1 != i {
ans = max(ans, 0)
}
// 如果乘积小于0,就需要首尾两端的负数,挨个取消来判断乘积
if preP < 0 && len(fuNums) > 0 {
tmpP := preP
if fuNums[0] < fuNums[len(fuNums)-1] {
}
for j:=left; j<=fuNums[0] && j<i-1; j++ {
tmpP /= nums[j]
}
ans = max(tmpP, ans)
tmpP = preP
for j:=i-1; j>=fuNums[len(fuNums)-1] && j>left; j-- {
tmpP /= nums[j]
}
// fmt.Println(2, tmpP)
ans = max(tmpP, ans)
}
fuNums = make([]int, 0)
if i != len(nums) - 1 {
product = 0
}
left = i+1
} else if nums[i] < 0 {
fuNums = append(fuNums, i)
}
}
return ans
}
func max(x, y int) int {
if x > y {
return x
}
return y
}