LeetCode 152. 乘积最大子数组

题目链接: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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值