LeetCode 152 乘积最大子数组

题目描述

给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个32位整数。

思路

这一题用普通的连续子数组思路求解时有一个问题:子问题的最优解不一定是总体的最优局部解。也就是不满足最优子结构,例如:[-2,3,-4],这个用例中,[-2,3]的最大乘积是3,而不是-6,但是[-2,3,4]的最大乘积需要让-2和3相乘得到-6,然后-6再和-4相乘得到24。解决方式是再维护一个dp数组,也就是一共有两个dp数组,其中一个称为dp_max,另一个称为dp_min。

  • dp_max:dp_max[i]表示数组nums中以nums[i]结束的连续子数组的最大乘积。
  • dp_min:dp_min[i]表示数组nums中以nums[i]结束的连续子数组的最小乘积。

然后

  • 在求解dp_max数组的过程中,把dp_min[i-1] * nums[i]作为一个候选值
  • 在求解dp_min数组的过程中,把dp_max[i-1] * nums[i]作为一个候选值

具体步骤

1 确定dp数组的含义

  • dp_max:dp_max[i]表示数组nums中以nums[i]结束的连续子数组的最大乘积。
  • dp_min:dp_min[i]表示数组nums中以nums[i]结束的连续子数组的最小乘积。

2 确定状态转移方程

dp_max[i] = MAX{nums[i], dp_max[i - 1] * nums[i], dp_min[i - 1] * nums[i]}
dp_min[i] = MIN{nums[i], dp_min[i - 1] * nums[i], dp_max[i - 1] * nums[i]}

3 确定初始状态

初始状态就是dp_max[i] = nums[i], dp_min[i] = nums[i]

代码

class Solution {
    public int maxProduct(int[] nums) {
        int[] dp_max = new int[nums.length];
        int[] dp_min = new int[nums.length];
        System.arraycopy(nums, 0, dp_max, 0, nums.length);
        System.arraycopy(nums, 0, dp_min, 0, nums.length);
        for (int i = 1; i < nums.length; i++) {
            dp_max[i] = Math.max(Math.max(dp_max[i], dp_max[i - 1] * nums[i]), dp_min[i - 1] * nums[i]);
            dp_min[i] = Math.min(Math.min(dp_min[i], dp_min[i - 1] * nums[i]), dp_max[i - 1] * nums[i]);
        }
        int ans = Integer.MIN_VALUE;
        for (int i = 0; i < dp_max.length; i++) {
            ans = Math.max(ans, dp_max[i]);
        }
        return ans;
    }
}
posted @   wutao666  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示