LeetCode 热题 HOT 100 (016/100)【宇宙最简单版】

【动态规划】No. 0152 乘积最大子数组【中等】👉力扣对应题目指路

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
欢迎关注、订阅专栏 【力扣详解】谢谢你的支持!

题目描述:给你一个整数数组 nums ,找出数组中乘积最大的非空连续子数组,并返回该子数组所对应的乘积

  • 该子数组中至少包含一个数字

  • 测试用例的答案是一个 32-位 整数

  • 示例 :

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

🔥 思路:采用动态规划,建立 dp 数组,利用前序 dp 数组推导其自身 dp 值

  • nums[i] 结尾的非空连续子数组能得到的最大乘积与前序 0 ~ i-1 所对应的乘积情况有关
    • 实际仅与 i-1 有关,👉 见文末的代码优化版本⛳

参考如上思路,给出详细步骤如下:

  • 步骤一⭐确定 dp 数组含义:一维 dp 数组

    • dp[i] 的含义为:以 nums[i] 结尾的非空连续子数组能得到的 [最大乘积项, ⚡最小乘积项] 【💥 重要】
      • 不能只保留 最大乘积 项,因为需要应对 负负得正的情况:如对于 nums = [-2, -3, -4],处理 i=2(👉 -4) 位置时,需要前序⚡最小乘积 (最大负数,因为 -4 是负数) 来计算以 -4 结尾的非空连续子数组能得到的最大乘积
  • 步骤二⭐确定 dp 推导方式:前序 dp 数组推导得到,取如下三种情况的最大、最小值

    • 情况一:选择从 nums[i] 新开子数组,乘积对应 nums[i]
    • 情况二:选择继续前序子数组,为应对负负得正情况,考虑两种乘积情况
      • 前序最大乘积项乘以当前值(👉 dp[i-1][0]*nums[i])和前序最小乘积项乘以当前值(👉 dp[i-1][1]*nums[i]
  • 步骤三⭐根据 dp 数组含义,初始化 dp 数组:

    • 由前序 i-1 推导,所以只需要关注最前面一个数的 dp 初值
      • dp[0] = [nums[0], nums[0]]
    • 根据推导公式,其他位置得初值会被覆盖、任意数均可(本代码中赋值 [0, 0])
class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        dp = [[0, 0] for _ in nums]  # ------------------------------------------------- step 1
        # 递推公式初始化: # ------------------------------------------------------------ step 3
        dp[0] = [nums[0], nums[0]]
        result = nums[0]

        for i in range(1, len(nums)):
        	# -------------------------------------------------------------------------- step 2
            dp[i][0] = max(nums[i], dp[i-1][0]*nums[i], dp[i-1][1]*nums[i])
            dp[i][1] = min(nums[i], dp[i-1][0]*nums[i], dp[i-1][1]*nums[i])
            result = max(dp[i][0], result)
        return result

⛳ 由于只用到了前面一位的 dp 值:dp[i-1],可进一步压缩 dpimin, imax;具体代码如下:

class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        imin, imax = nums[0], nums[0]
        result = nums[0]

        for i in range(1, len(nums)):
            imin, imax = min(nums[i], imin*nums[i], imax*nums[i]), max(nums[i], imin*nums[i], imax*nums[i])
            result = max(imax, result)
        return result

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
🔥 LeetCode 热题 HOT 100

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值