首页 > leetcode-152 乘积最大子序列

leetcode-152 乘积最大子序列

题目描述:

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

示例 1:

输入: [2,3,-2,4]

输出: 6

解释: 子数组 [2,3] 有最大乘积 6。

示例 2:

输入: [-2,0,-1]

输出: 0

解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

该题目求最大子序列的乘积,参考leetcode-52 最大子序和中的暴力解法,穷举所有元素的可能性:

int maxSubArray(vector<int>& nums) { if(nums.size() == 1) return nums[0];int res = nums[0];for (int i = 1;i < nums.size(); ++i) { int pre = _maxSubArray(nums,i);res = max(res,pre);}return res;
}
int _maxSubArray(vector<int> &nums, int index) { if(index == 0) { return nums[0];}int pre = _maxSubArray(nums, index - 1);int res = max(nums[index] * pre, nums[index]);return res;
}

但是和的形态和积的形态还是有差异的,针对-2 2 -3的数列,以上方法求的最大乘积为2,但是实际上是12

乘积存在 之前的最小值(负数)再乘上当前的一个负数,就有可能变为最大值。

所以针对乘积的最大子序列,使用动态规划的方式,且状态转移方程需要维护两种状态,一种最大值,一种最小值:

  • 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])

实现如下:

int maxProduct(vector<int>& nums) { if(nums.size() == 1) return nums[0];int dp[2][2],res; //仅仅需要常数的空间,每个方程仅需要保存当前状态和前一个状态dp [0][0] = nums[0]; //最大值的方程dp [0][1] = nums[0]; //最小值的方程res = nums[0];for (int i = 1;i < nums.size(); ++i) { int x = i % 2; //转换下标int y = (i - 1) % 2;dp[x][0] = max(max(dp[y][0] * nums[i], dp[y][1] * nums[i]),nums[i]);dp[x][1] = min(min(dp[y][0] * nums[i], dp[y][1] * nums[i]),nums[i]);res = std::max(res, dp[x][0]);}return res;
}

更多相关:

  • 题目:调整数组顺序使奇数位于偶数前面 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。 示例: 输入:nums = [1,2,3,4] 输出:[1,3,2,4] 注:[3,1,2,4] 也是正确的答案之一。 提示: 1 <= nums.length <=...

  • 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1]...

  • 题目描述如下: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 方法一(暴力求解): 针对数组中的每一个元素,穷举所有的可能性,...

  • WinForm绘制带有升序、降序的柱形图   private void HuiZhiTu( string strPaiXu){//初始数据int[] nums = { 150, 89, 200, 60, 70, 90 };if (strPaiXu == "升序"){//冒泡排序for (int i = 0; i <...

  • 题目:正则表达式匹配 请实现一个函数用来匹配包含'. '和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"和"ab*a"均不匹配。 示例 1:...

  • 题意:就是在n*m的格子中放“炮”(中国象棋中的棋子)问有多少种放法,使得没有任意的两个炮相互攻击 思路:我们很容易的得到一列或者一行中最多放下两个炮(我也只能得到这些了,满脑子状压,但数据范围有100),这篇博客些的很好(传送门),我们定义dp[i][j][k]代表前i行我们有j列式有2个棋子,有k列是一个棋子,那么我们空的列的个数...

  • 虽然也是一道dp的入门题,但就是想不到,或者说不会实现。dp还是要多做题。 链接:https://www.luogu.org/problemnew/show/P1164   我们可以设dp[i][j]表示以考虑完第i件,恰好消费j元的方案数。那么dp[i][j]=dp[i-1][j]+dp[i-1][j-a[i]],也就是讨论第i件点...

  • bzoj1260,懒得复制,戳我戳我 Solution: 这种题目我不会做qwq,太菜了区间打牌(dp) 用f[l][r]表示从l到r最少需要染几次色。状态转移方程: 1.(f[l][r]=min(f[l][i],f[i+1][r]) (l<=i

  • 题目背景 博弈正在机房颓一个叫做《模拟城市2.0》的游戏。 2048年,经过不懈努力,博弈终于被组织委以重任,成为D市市委书记!他勤学好问,励精图治,很快把D市建设成富强民主文明和谐的美好城市。为了进一步深化发展,他决定在海边建立一个经济开发区。 题目描述 已知开发区的建筑地块是一个n×nn imes nn×n的矩形,而开发...

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...