最大子序列积问题
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时结束:
- maxPre = max(maxPre * A[i], minPre*A[i], A[i]);
- minPre = min(maxPre * A[i], minPre*A[i], A[i]);
- 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