《Leetcode》152.乘积最大子数组

128 篇文章 0 订阅
35 篇文章 0 订阅

给你一个整数数组 nums ,请你找出数组中乘积最大的连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。

例1

输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。

例2

输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

思路:如果这个数组都是正数或者说负数的个数都是奇数的话,那么整个数组的乘积就是最大的了。所以问题的关键在于负数,如果遇见负数怎么办。初始话两个值,这两个值是数组遍历到这块的时候最大值和最小值。如果遍历数组是正数的话,那么最大值就等于和该元素的成绩,如果是遇见是负数的话,那么把之前计算的最大值和最小值进行交换,这个最大值肯定是遇见的负数,这个最小值就是前面所有正数的乘积再乘以负数。然后这样不断的更新最大值。

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        ans = float('-inf')
        Max,Min=1,1
        for i in nums:
            if i<0:
                Max,Min = Min,Max
            Max = max(Max*i,i)
            Min = min(Min*i,i)
            print('Max:{},Min:{}'.format(Max,Min))
            ans = max(ans,Max)
        return ans
Max:2,Min:2
Max:6,Min:3
Max:-2,Min:-12
Max:4,Min:-48

在补充两个纯正的动态规划

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        

        #动态规划
        if not nums:
            return  0
        dp_max = [0]*len(nums)
        dp_min = [0]*len(nums)
        dp_max[0],dp_min[0] = nums[0],nums[0]
        #dp_max[i],表示以i结尾的最大连续子数组
        #dp_min[i],表示以i结尾的最小连续子数组
        for i in range(1,len(nums)):
            #这样写动态转移方程就已经考虑到正负性了
            dp_max[i] = max(dp_max[i-1]*nums[i],max(dp_min[i-1]*nums[i],nums[i]))
            dp_min[i] = min(dp_min[i-1]*nums[i],min(dp_max[i-1]*nums[i],nums[i]))

        #找到dp_max中最大的数字即可
        return max(dp_max)




        #状态压缩
        max_F,min_F = nums[0],nums[0]
        ans = nums[0]
        size = len(nums)
        for i in range(1,size):
            #使用两个变量记录上一个时刻的值
            #dp[i]仅和上一个状态量有关系
            mx,mi = max_F,min_F
            max_F = max(mx*nums[i],max(nums[i],mi*nums[i]))
            min_F = min(mi*nums[i],min(nums[i],mx*nums[i]))
            ans = max(max_F,ans)
        return ans
  •  因为有负数,需要考虑负数如何进行处理
  • dp_max[i] = max(dp_max[i-1]*nums[i],max(dp_min[i-1]*nums[i],nums[i]))
  • dp_min[i]  = min(dp_min[i-1]*nums[i],min(dp_max[i-1]*nums[i],nums[i]))

总结:又是一个动态规划的题目,和53题有点类似,但是感觉动态规划的题目都不是那么好想,多思考,多思考!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值