最大连续子序列之和,最大连续子序列乘积
2014-10-30 01:01
330 查看
最大连续子序列之和问题描述为:数组中里有正数也有负数,连续的一个或多个整数组成一个子数组,每个子数组都有一个和,求所有子数组的和的最大值。分析,对数组a进行一遍扫描,sum[i] 为前i个元素中,包含第i个元素且和最大的连续子数组,MaxSum保存当前子数组中最大和,对于a[i+1]来说,sum[i+1] = sum[i]+a[i+1],此时如果sum[i+1]<0,那么sum需要重新赋0,从i+1之后开始累加,如果sum[i+1]>0,那么MaxSum = max(MaxSum, Sum[i+1])。代码如下:
最大连续子序列乘积,问题描述和前面求最大连续子序列之和类似:给一个浮点数序列,取最大乘积连续子串的值。这里需要重点注意的是乘积需要注意正负号,需要考虑到有偶数个的情况,所以计算时,不止要保存当前最大乘积,也要保存当前最小乘积。代码如下:
在网上看到使用动态规划的算法来处理此题目。假设从数组开头 i 到结尾 j 的范围,求出所有元素为结尾的子序列最大值,取其中最大的那个即为所求的最大连续子序列乘积。假设max(i, k)表示从数组 i 开始到 j 结束的范围内,包含 j 作为结尾的最大连续子序列乘积,注意不一定以 i 作为起始,问题可以概括为max = max(max(i, i), max(i, i+1), ……, max(a, k), ……., max(i, j)) 。那么对于max(i, k)后面的max(i, k+1)来说,会有如下几种情况:
max(i, k)和a[k+1]均为正数,且max(i, k)*a[k+1] > max(i, k),那么有 max(i, k+1) = max(i, k) * a[k+1]
max(i, k)和a[k+1]一正一负,如果max(i, k)>0,a[k+1] < 0,那么乘积<0,而max(i, k+1)要包含a[k+1],所以max(i, k+1) = a[k+1],反之亦然
max(i, k)为正数,a[k+1]为负数,不过max(i, k)之前相连的序列里有负数,那么前面包含负数的这个序列,必然是一个前面序列的最小值,此时max(i, k+1) = min(i, k) * a[k+1]
概括起来,包含第k+1个元素为结尾的序列最大乘积应该取自上述三种情况之一:max(i, k+1) = max(max(i, k) * a[k+1], a[k+1], min(i, k) * a[k+1])。
按照同样的道理,我们求得的包含k+1在内结尾的最小乘积序列为:min(i, k+1) = min(min(i, k) * a[k+1], a[k+1], max(i, k) * a[k+1])。
代码如下:
int maxSum(int *nArray, int nSize, int &nBegin, int &nEnd) { int nSum = 0, nMaxSum = 0; int nNewBegin = 0; //记录新的开始下标 nBegin = nEnd = 0; //记录最大连续子数组和的起始于结束下标 for(int i=0; i!=nSize; i++) { nSum += nArray[i]; if(nSum >= nMaxSum) { nMaxSum = nSum; nBegin = nNewBegin; nEnd = i; } else if(nSum < 0) { nSum = 0; nNewBegin = i+1; } } return nMaxSum; } int _tmain(int argc, _TCHAR* argv[]) { int Array[5] = {2, -3, 4, 5, -100}; int nBegin = 0, nEnd = 0; int nMaxSum = maxSum(Array, sizeof(Array)/sizeof(*Array), nBegin, nEnd); cout<<nMaxSum<<endl; cout<<"开始下标为["<<nBegin<<"], 结束下标["<<nEnd<<"]"<<endl; return 0; }
最大连续子序列乘积,问题描述和前面求最大连续子序列之和类似:给一个浮点数序列,取最大乘积连续子串的值。这里需要重点注意的是乘积需要注意正负号,需要考虑到有偶数个的情况,所以计算时,不止要保存当前最大乘积,也要保存当前最小乘积。代码如下:
double maxProduct(double a[], int nLen, int &nBegin, int &nEnd) { int nNewBegin = 0; nBegin = nEnd =0; double dCurMax = 1.0f; double dCurMin = 1.0f; double dMax = 1.0f; double dMin = 1.0f; for(int i=0; i!=nLen; i++) { dCurMax *= a[i]; dCurMin *= a[i]; cout<<"dCurMax = "<<dCurMax<<", dCurMin = "<<dCurMin<<endl; if(dCurMax > dMax) { dMax = dCurMax; nBegin = nNewBegin; nEnd = i; } if(dCurMin > dMax) { dMax = dCurMin; nBegin = nNewBegin; nEnd = i; } if(dCurMax < dMin) { dMin = dCurMax; } if(dCurMin < dMin) { dMin = dCurMin; } if(dCurMax == 0 || dCurMin == 0) { dCurMax = dCurMin = 1; nNewBegin = i+1; } cout<<"dMax = "<<dMax<<", dMin = "<<dMin<<endl; cout<<"begin = "<<nBegin<<", end = "<<nEnd<<endl; } return dMax; } int _tmain(int argc, _TCHAR* argv[]) { double a[] = { -2.5, 4, 0, 3, 0.5, 8, -2, -2}; int nBegin, nEnd; int max = maxProduct(a, sizeof(a)/sizeof(*a), nBegin, nEnd); cout<<max<<endl; cout<<nBegin<<" "<<nEnd<<endl; return 0; }
在网上看到使用动态规划的算法来处理此题目。假设从数组开头 i 到结尾 j 的范围,求出所有元素为结尾的子序列最大值,取其中最大的那个即为所求的最大连续子序列乘积。假设max(i, k)表示从数组 i 开始到 j 结束的范围内,包含 j 作为结尾的最大连续子序列乘积,注意不一定以 i 作为起始,问题可以概括为max = max(max(i, i), max(i, i+1), ……, max(a, k), ……., max(i, j)) 。那么对于max(i, k)后面的max(i, k+1)来说,会有如下几种情况:
max(i, k)和a[k+1]均为正数,且max(i, k)*a[k+1] > max(i, k),那么有 max(i, k+1) = max(i, k) * a[k+1]
max(i, k)和a[k+1]一正一负,如果max(i, k)>0,a[k+1] < 0,那么乘积<0,而max(i, k+1)要包含a[k+1],所以max(i, k+1) = a[k+1],反之亦然
max(i, k)为正数,a[k+1]为负数,不过max(i, k)之前相连的序列里有负数,那么前面包含负数的这个序列,必然是一个前面序列的最小值,此时max(i, k+1) = min(i, k) * a[k+1]
概括起来,包含第k+1个元素为结尾的序列最大乘积应该取自上述三种情况之一:max(i, k+1) = max(max(i, k) * a[k+1], a[k+1], min(i, k) * a[k+1])。
按照同样的道理,我们求得的包含k+1在内结尾的最小乘积序列为:min(i, k+1) = min(min(i, k) * a[k+1], a[k+1], max(i, k) * a[k+1])。
代码如下:
int maxProduct_DP(double a[], int n) { double maxCur = 1.0f; double minCur = 1.0f; double maxTmp = maxCur; double minTmp = minCur; double result = 0.0f; for(int i=0; i!=n; i++) { maxTmp = max(maxCur*a[i], max(a[i], minCur*a[i])); minTmp = min(maxCur*a[i], min(a[i], minCur*a[i])); maxCur = maxTmp; minCur = minTmp; result = max(result, maxCur); } return result; }
相关文章推荐
- 求一个浮点数的连续子序列最大乘积 (2013 小米校园招聘笔试题)
- 最大连续子序列乘积
- 九度OJ 1501 最大连续子序列乘积 -- 动态规划
- 最大连续子序列乘积
- 九度OJ 1501 最大连续子序列乘积 -- 动态规划
- 最大连续子序列和/乘积
- 题目1501:最大连续子序列乘积
- 最大连续子序列乘积
- 最大连续子序列乘积_1501
- 最大连续子序列乘积
- 小米2013校园招聘笔试题-最大连续子序列乘积
- 利用C语言来求最大连续子序列乘积的方法
- 最大连续子序列和,乘积,最长递增子串,最长公共子串,子序列等问题(动态规划等)
- [C++]最大连续子序列乘积
- 最大连续子序列乘积
- 最大连续子序列和/乘积
- 动态规划:最大连续子序列乘积 分类: c/c++ 算法 2014-09-30 17:03 656人阅读 评论(0) 收藏
- 动态规划:最大连续子序列乘积
- Maximum product of consecutive subsequence(最大连续子序列乘积)
- 题目1501:最大连续子序列乘积