首页 > 其他分享 >Leetcode-152 乘积最大子数组

Leetcode-152 乘积最大子数组

时间:2024-05-24 15:29:19浏览次数:28  
标签:min 152 乘积 nums max imin imax Leetcode dp

Leetcode-152 乘积最大子数组

题目描述

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

示例1:

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

示例2:

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

解题思路

一种错误的解题思路

dp[i]表示以第i个元素结尾的乘积最大子数组的乘积,你可能会想到这样的转移方程 dp[i] = max(dp[i-1] * nums[i], dp[i-1]),但是当前位置的最优解未必是由前一个位置的最优解转移得到!比如[3, 4, -2, 7, -1],我们使用上述转移方程,最后的结果是12,实际上应该是3 * 4 * (-2) * 7 * (-1)。

正确的思路(一)

  • 当前位置如果是一个负数,那么我们希望以它前一个位置结尾的某个段的积也是个负数,这样就可以负负得正,并且我们希望这个积尽可能「负得更多」,即尽可能小。
  • 如果当前位置是一个正数的话,我们更希望以它前一个位置结尾的某个段的积也是个正数,并且希望它尽可能地大。
    于是这里我们可以再维护一个 dp(min)[i],它表示以第i个元素结尾的乘积最小子数组的乘积,那么我们可以得到这样的动态规划转移方程:
    dp(max)[i] = max(dp(max)[i-1] * nums[i], dp(min)[i-1] * nums[i], nums[i]),
    dp(min)[i] = min(dp(max)[i-1] * nums[i], dp(min)[i-1] * nums[i], nums[i])

C++代码

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        vector<int> dp_max(nums), dp_min(nums);
        for (int i = 1; i < nums.size(); i++) {
            dp_max[i] = max(dp_max[i-1] * nums[i], max(dp_min[i-1] * nums[i], nums[i]));
            dp_min[i] = min(dp_max[i-1] * nums[i], max(dp_min[i-1] * nums[i], nums[i]));
        }
        return *max_element(dp_max.begin(), dp_max.end());
    }
};

正确的思路(二)

imax 为当前最大值, imin 为当前最小值,考虑到 nums[i]正负的情况,那么最大值res可以这样求取:

  1. nums[i] > 0时:imax = max(imax * nums[i], nums[i])imin = min(imin * nums[i], nums[i])
  2. nums[i] <= 0时:imax = max(imin * nums[i], nums[i])imin = min(imax* nums[i], nums[i])
    在此过程更新最大值res就可以

C++代码

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int res = INT_MIN, imax = 1, imin = 1;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] > 0) {
                imax = max((imax * nums[i]), nums[i]);
                imin = min((imin * nums[i]), nums[i]);
            }
            if (nums[i] <= 0) {
                int tmp = imax;
                imax = max((imin * nums[i]), nums[i]);
                imin = min((tmp * nums[i]), nums[i]);
            }
            res = max(res, imax);
        }
        return res;
    }
};

这里,可以进行逻辑的简化:如果 nums[i] < 0,我将imax 和 imin 互换即可,那么当前最大值和最小值就可以写成一种形式:

class Solution {
public:
    int maxProduct(vector<int>& nums) {
        int res = INT_MIN, imax = 1, imin = 1;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] < 0) {
                int tmp = imax;
                imax = imin;
                imin = tmp;
            }
            imax = max((imax * nums[i]), nums[i]);
            imin = min((imin * nums[i]), nums[i]);

            res = max(res, imax);
        }
        return res;
    }
};

标签:min,152,乘积,nums,max,imin,imax,Leetcode,dp
From: https://blog.csdn.net/weixin_51332735/article/details/139151767

相关文章

  • LeetCode Greatest Common Divisor of Strings All In One
    LeetCodeGreatestCommonDivisorofStringsAllInOneLeetCode1071errorsfunctiongcdOfStrings(str1:string,str2:string):string{letresult=``;lettemp=[];if(str1.length>str2.length){letreg=newRegExp(str2,'g'......
  • 【LeetCode】59. 螺旋矩阵 II
    题目:59.螺旋矩阵II解题思路手动模拟螺旋矩阵,分别实现四个方向的代码,将数组依次填入数组中即可需要注意的是,如果n为奇数,说明最后只剩下中间的一个位置,将最后一个数直接填入即可;若n为偶数,则正好能够遍历n/2遍classSolution{publicint[][]generateMatrix(intn){......
  • [LeetCode] 1863. Sum of All Subset XOR Totals
    TheXORtotalofanarrayisdefinedasthebitwiseXORofallitselements,or0ifthearrayisempty.Forexample,theXORtotalofthearray[2,5,6]is2XOR5XOR6=1.Givenanarraynums,returnthesumofallXORtotalsforeverysubsetofnums.......
  • 152- Maximum Produce Subarray-最大子数组之乘积
    问题描述Givenanintegerarray nums,finda subarray.thathasthelargestproduct,andreturn theproduct.Thetestcasesaregeneratedsothattheanswerwillfitina 32-bit integer.解释:找出一个数组中乘积最大的子数组,返回子数组的乘积。案例:Input......
  • 152. 乘积最大子数组
    给你一个整数数组nums,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个32-位整数。示例1:输入:nums=[2,3,-2,4]输出:6解释:子数组[2,3]有最大乘积6。示例2:输入:nums=[-2,0,-1]输......
  • LeetCode 1353. Maximum Number of Events That Can Be Attended
    原题链接在这里:https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended/description/题目:Youaregivenanarrayof events where events[i]=[startDayi,endDayi].Everyevent i startsat startDayi andendsat endDayi.Youcanattend......
  • vscode leetcode 插件
    区域测试//@lcprcase=start//"PAYPALISHIRINGGGG"\n3\n//@lcprcase=enddiy参数用于调试不同类型的参数和函数//@lcpr-div-debug-arg-start//funName=alternateDigitSum//paramTypes=["number"]//@lcpr-div-debug-arg-endfunName:函数名称paramTypes......
  • LeetCode 918. Maximum Sum Circular Subarray
    原题链接在这里:https://leetcode.com/problems/maximum-sum-circular-subarray/description/题目:Givena circularintegerarray nums oflength n,return themaximumpossiblesumofanon-empty subarray of nums.A circulararray meanstheendofthearray......
  • 40. 组合总和 II(leetcode)
    https://leetcode.cn/problems/combination-sum-ii/description/classSolution{List<List<Integer>>res=newArrayList<>();LinkedList<Integer>path=newLinkedList<>();intsum=0;publicList<List&l......
  • LeetCode 1669. Merge In Between Linked Lists
    原题链接在这里:https://leetcode.com/problems/merge-in-between-linked-lists/description/题目:Youaregiventwolinkedlists: list1 and list2 ofsizes n and m respectively.Remove list1'snodesfromthe ath nodetothe bth node,andput list2 in......