最大子序列积

最大子序列积问题

Maximum Product Subarray          2014.10.13      

题目描述(来自leetcode,题目

寻找一个序列的连续子序列使其乘积达到最大(最少含有一个元素),并返回最大积。

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

例如:

给定序列 [2, 3, -2, 4],连续子序列[2,3] 有最大积等于6.

给定序列 [3, -1, 4],连续子序列[4] 有最大积等于 4.

算法一:

我们知道在求最大子序列和的时候有一种时间复杂度为O(N^3)的方法,即穷举式尝试所有的可能,运行时间为O(N^3)由于其效率问题,通常不被采用,为了更好理解这个问题,我们首先给出了这个算法程序

code

/*
* 最大子序列积 O(N^3) 算法
* Cubic maximum contiguous subsequence product algorithm
*/
int maxSubProduct1(int A[], int n)   // 传入数组地址和元素个数
{
	if( n== 0 )
		return 0;
	int maxPro = 1;     // 保存结果
	for( int i = 0; i < n; i++ )
	{
		for( int j = i; j < n; j++ )
		{
			int thisPro = 1;      // 保存A[i]*...*A[j]的结果
			for( int k = i; k <= j; k++ )
				thisPro *= A[k];

			if( thisPro > maxPro )
				maxPro = thisPro;
		}
	}
	return maxPro;
}

算法二:

由于我们不需要知道最佳子序列在哪里,因此可以如下改进算法一,改进后的算法时间复杂度为O(N)。

我们知道序列元素A[i]有可能为负,而负负又得正,因此不能只保留A[i]前的最大序列积,还应保留最小序列积。

因此我们定义A[i]前紧邻A[i]的最大序列积为maxPre,A[i]前紧邻A[i]的最小序列积为minPre,A[i]前的最大序列积为maxhere。

我们只需要对数据进行一次扫描,一旦A[i]被处理,它就不再需要被记忆,并完成以下步骤,直到i为n时结束:

  1. maxPre = max(maxPre * A[i], minPre*A[i], A[i]);
  2. minPre = min(maxPre * A[i], minPre*A[i], A[i]);
  3. maxhere = max(maxhere, maxPre);
  • return maxhere.

code

/*
* 最大子序列积 O(N) 算法
* Linear-time maximum contiguous subsequence product algorithm
*/
int maxSubProduct2(int A[], int n)
{
	if (n == 0)
		return 0;
	int maxPre = A[0];  // 该元素前相邻子序列最大积
	int minPre = A[0];  // 该元素前相邻子序列最小积
	int maxhere = A[0];  // 存储结果
	int temp;
	for (int i = 1; i < n; i++)
	{
		temp = maxPre;     // 先保存下maxPre的值
		maxPre = max(max(maxPre * A[i], minPre * A[i]), A[i]);
		minPre = min(min(temp * A[i], minPre * A[i]), A[i]);
		if(maxPre > maxhere)
			maxhere = maxPre;
	}
	return maxhere;
}

做一个对自己有点要求的人。



时间: 2024-10-09 12:47:03

最大子序列积的相关文章

[转]常见的动态规划问题分析与求解

动态规划(Dynamic Programming,简称DP),虽然抽象后进行求解的思路并不复杂,但具体的形式千差万别,找出问题的子结构以及通过子结构重新构造最优解的过程很难统一,并不像回溯法具有解决绝大多数问题的银弹(全面解析回溯法:算法框架与问题求解).为了解决动态规划问题,只能靠多练习.多思考了.本文主要是对一些常见的动态规划题目的收集,希望能有所帮助.难度评级受个人主观影响较大,仅供参考. 目录(点击跳转) 动态规划求解的一般思路 备忘录法 1.硬币找零 扩展1:单路取苹果 扩展2:装配线

最大子数组之和、最大子数组之积、最长递增子序列求法

昨天做爱奇艺笔试题,最后一道编程题是求整型数组最长递增子序列,由于时间关系,没有完全写出来,今天重新来做做这一系列题. <1> 最大子数组之和 首先从最简单的最大子数组之和求取.数组里有正数.负数.零.设包含第 i 个元素的子数组的和为 Sum,则Sum的值为 Sum(i) = Sum(i-1) + arrey[i]; 显然如果arrey[i]<=0,则Sum(i)<=Sum(i-1);则必须把Sum(i)=arrey[i];同时maxSum用来保存Sum最大值.时间复杂度为o(n

LintCode-乘积最大子序列

找出一个序列中乘积最大的连续子序列(至少包含一个数). 样例 比如, 序列 [2,3,-2,4] 中乘积最大的子序列为 [2,3] ,其乘积为6. 分析:访问到每个点的时候,以该点为子序列的末尾的乘积,要么是该点本身,要么是该点乘以以前一点为末尾的序列,注意乘积负负得正,故需要记录前面的最大最小值. 代码: class Solution { public: /** * @param nums: a vector of integers * @return: an integer */ int m

[经典] 最X(长 | 大和 | 大积)Y(子序列 | 子字符串)

Note: 子序列,可以不连续:子字符串,必须连续. 以下题目按在我看看来的难度从易到难排列: 最大和子序列(Maximum sum subsequence) 这道题纯属娱乐...应该不会有人出这种题吧.方案是遇到正数就放入序列. vector<int> msseq(vector<int> &num) { vector<int> result; for(int i : num) if(i > 0) result.push_back(i); return r

力扣152,53题,最大子序列求和and积

本内容为最大子序列的求和和求积.采用DP的思路, 当前值加上小于之前值,则从该节点重新算起. 这个代码只能返回其结果值,但不能返回最后的子序列(待修改). class Solution: def maxSubArray(self,arr): #最大子数组和的DP求解 if not arr:return cur_sub,max_sub = arr[0],arr[0] #记录当前集合和最大集合 res = [arr[0]] for i in range(1,len(arr)): #从第二个开始遍历

LeetCode--152--乘积最大子序列(python)

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数). 示例 1: 输入: [2,3,-2,4]输出: 6解释: 子数组 [2,3] 有最大乘积 6.示例 2: 输入: [-2,0,-1]输出: 0解释: 结果不能为 2, 因为 [-2,-1] 不是子数组. 令imax,imin为当前索引的最大最小值 当遇到负数的时候,负数乘最大值就变成了最小值,所以应该在比较之前把imax和imin调换 1 class Solution: 2 def maxProduct(

HDU 4561 连续最大积 (模拟题)

#include <iostream> #include<cstdio> using namespace std; int a[50000+100],n; int solve(int s,int e) { int i,cnt=0,st,ed,flag=1,ans=0; //if(s==n+1) return 0; for(i=s;i<e;i++) { if(a[i]==-2) { if(flag) { flag=0; st=i;//记录此区间内-2第一次出现的位置 } ed=

DP之子序列问题

最近算法课又学习了一遍动态规划,看了一些求子序列的问题,特意集中mark一下以作备忘.. 最长上升子序列  问题描述 对于给定的整数数组序列,若它的一个子序列的元素是升序排列的,则称这个子序列是一个上升子序列.问题要求对于一给定整数数组,要求找到一个它的最长上升子序列. 算法实现 设A为给定的数组,A[i] 表示数组A的第i个元素,DP[i]表示表示以A[i]为结尾的最长上升子序列的长度,初始化DP[i]=0(i=1,2.....len(A)),则有状态转移方程:DP[i]=max{1,DP[j

LeetCode——152. 乘积最大子序列

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数). 示例 1: 输入: [2,3,-2,4] 输出: 6 解释: 子数组 [2,3] 有最大乘积 6. 示例 2: 输入: [-2,0,-1] 输出: 0 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组. https://leetcode-cn.com/problems/maximum-product-subarray/ 动态规划 其实这道题最直接的方法就是用 DP 来做,而且要用两个 dp 数组