DP_medium_152_乘积最大子数组

题目描述

在这里插入图片描述

思路

方法一: 暴力 - 时间复杂度 O ( n ) O(n) O(n)

0在数组中是个特殊元素,因为任何元素和0相乘都为0,(DP思路没写出来时)我想着以0 为切分点,将原数组切分成一些子数组,这些子数组中不包含0,然后单考虑所有的子数组:

  • 若子数组中不含负数,或者包含偶数个负数,那么该子数组的最大值就是 所有元素的乘积
  • 若子数组中含有奇数个负数,易证:该子数组的最大值是 最后一个负数之前的所有元素的乘积(不含最后一个负数) 或 第一个负数之后的所有元素的乘积(不含第一个负数)。
  • 然后取各个子数组中的最大值即可

例如 对于[1,2,3,4,0, 5,-6,-7,8,-9],

  • 被分为[1,2,3,4] 和 [5,-6,-7,8,-9] 两个子数组
  • 其中 [5,-6,-7,8,-9] 的最大值是 [5,-6,-7,8] 或者 [-7,8,-9] 的乘积
class Solution:
    def maxProduct(self, nums: List[int]) -> int:

        def handle(left, right):  # 计算一个不含0的整数数组的最大值
            if left == right:
                self.res = max(self.res, nums[left])
                return
            cnt = 0
            mid = 1
            first_index, end_index = 0, 0
            for i in range(left, right+1):
                mid *= nums[i]
                if nums[i] < 0:
                    cnt += 1
                    if cnt == 1:
                        first_index = i
                    end_index = i
            if cnt % 2:  # 为奇数
                key = 1
                for i in range(left, first_index+1):
                    key *= nums[i]
                self.res = max(self.res, mid//key)
                key = 1
                for i in range(end_index, right+1):
                    key *= nums[i]
                self.res = max(self.res, mid//key)
            else:
                self.res = max(self.res, mid)
                

        
        if len(nums) == 1: return nums[0]  # 只有一个元素 ,特判
        self.res = 0
        i = 0
        while i < len(nums) and nums[i] == 0:  # 找第一个不为0的元素, 如 [0,0,0,0,1,2,3]
            i += 1
        if i == len(nums): return 0
        j = i + 1
        while j < len(nums):
            if nums[j] == 0:
                handle(i, j-1)
                # print(i, j-1)
                i = j
                while i < len(nums) and nums[i] == 0:  # 找下一个不为0的元素,因为可能存在好多0 如[1,0,0,0,0,2,3]
                    i += 1
                j = i+1
            else:
                j += 1
        if j == len(nums) and nums[j-1] != 0:
            handle(i, j-1)
        return self.res

方法二: DP - 时间复杂度 O ( n ) O(n) O(n)

Reference:
https://leetcode-cn.com/problems/maximum-product-subarray/solution/cheng-ji-zui-da-zi-shu-zu-by-leetcode-solution/

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        max_num, min_num, res = nums[0], nums[0], nums[0]
        for i in range(1, len(nums)):
            if nums[i] < 0:
                max_num, min_num = min_num, max_num
            max_num = max(max_num*nums[i], nums[i])
            min_num = min(min_num*nums[i], nums[i])
            res = max(res, max_num)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值