力扣--乘积最大子数组

博客探讨了一道编程题,要求找到整数数组中具有最大乘积的连续子数组。作者首先尝试了一种方法,但遇到错误,然后改进了算法,使用动态规划维护最大值和最小值数组,最终成功求解。代码实现中涉及到了对负数处理的特殊情况。
摘要由CSDN通过智能技术生成

Given an integer array nums, find a contiguous non-empty subarray within the array that has the largest product, and return the product.

It is guaranteed that the answer will fit in a 32-bit integer.

A subarray is a contiguous subsequence of the array.

Example 1:

Input: nums = [2,3,-2,4]
Output: 6
Explanation: [2,3] has the largest product 6.
Example 2:

Input: nums = [-2,0,-1]
Output: 0
Explanation: The result cannot be 2, because [-2,-1] is not a subarray.

Constraints:

1 <= nums.length <= 2 * 104
-10 <= nums[i] <= 10
The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

随手记录一下解题过程:
刚看到这道题,跟LIS很像,但不同的是隐形的增加了条件:[2,-1,-2]如果用LIS得出结果是2,而正确答案是4,也就是说,增加的隐形条件是1、不知道负数的个数 ;2、不能通过得到当前最大值直接相乘得出答案。而我又注意到,当进行2*(-1)判断时,程序会把2*(-1)判断成最小,但是下一步计算2*(-1)又是最大,于是有个想法:将当前相乘结果为负数的数据存储起来,那么代码就是:

#include <bits/stdc++.h>
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int len = nums.size();
        int dp[len];
        memset(dp,0,sizeof(dp));
        dp[0] = nums[0];
        int ans = nums[0];
        int x=1;
        for(int i=1; i<len; i++){
        	dp[i] = dp[i-1]*nums[i];
         	if( nums[i] < 0){
         	dp[i] = max(dp[i-1]*nums[i], x*nums[i]);
         	}
         	/*请注意x只能在这个位置*/
            x = dp[i-1]*nums[i];
        }
        return ans;
    }
};

于是成功过了样例,卡在了[2,-2,-3,-4,5]上,这种数据我程序得出的结果是12,正确结果应该是60.
于是我就在思考,因为:60是通过(-3)*(-4)*5得到的,难道是两个for循环?可是即使是两个for循环也无法进行解决dp[i-1]*nums[i]得出是负数的那种情况。
回到第一种思路,第一种思路很好的解决了目前这个数是负数的情况,那么,如果放眼到全局,是不是就由一个数变到了一个数组?那也就是说,我们需要两个数组,一个存最大值,一个存最小值(可以想一想为什么是最小值)(答案:因为是一个正数乘上一个负数,那么这个新的数一定是最小值),于是代码如下:

#include <bits/stdc++.h>
class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int len = nums.size();
        int dp[len];
        int dm[len];
        memset(dp,0,sizeof(dp));
        memset(dm,0,sizeof(dm));
        dp[0] = nums[0];
        dm[0] = nums[0];
        int ans = nums[0];
        int x=1;
        int p,q;
        for(int i=1; i<len; i++){
            p = max(dp[i-1]*nums[i],dm[i-1]*nums[i]);
            dp[i] = max(p,nums[i]);

            q = min(dp[i-1]*nums[i],dm[i-1]*nums[i]);
            dm[i] = min(q,nums[i]);
            ans = max(ans,dp[i]);
        }
        return ans;
    }
};

完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九久呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值