首页 > 代码库 > 最大子序列积

最大子序列积

最大子序列积问题

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;
}





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









最大子序列积