最大序列和问题
来源:互联网 发布:mac 命令行卸载软件 编辑:程序博客网 时间:2024/06/05 02:19
最大子序列和的问题:就是给出一组数据,求出里面那几个前后连续的数的和最大。
书中给出4个算法,时间复杂度从O(N^3)降到O(N^2)再降到O(NlogN)最后到O(N),这就是人家跑完程序都走上人生巅峰了,你面对一组数据苍颜白发却还在等待结果...
//O(N^3)int maxSubSum1(const vector& a){int maxSum = 0;for (int i = 0; i < a.size(); ++i)for (int j = i; j < a.size(); ++j){int thisSum = 0;//这个for其实就是多余写出来...for (int k = i; k <= j; ++k)thisSum += a[k];if (thisSum > maxSum)maxSum = thisSum;}return maxSum;}//O(N^2) 优化的就是上一个算法里的forint maxSubSum2(const vector & a){int maxSum = 0;for (int i = 0; i < a.size(); ++i){int thisSum = 0;for (int j = i; j < a.size(); ++j) {thisSum += a[j];if (thisSum > maxSum)maxSum = thisSum;}}return maxSum;}//分治法O(NlogN)int maxSumRec(const vector &a, int left, int right){if (left == right)//只有一个元素if (a[left] > 0)return a[left];elsereturn 0;int center = (left + right) / 2;int maxLeftSum = maxSumRec(a, left, center);int maxRightSum = maxSumRec(a, center + 1, right);int maxLeftBorderSum = 0, leftBorderSum = 0;for (int i = center; i >= left; --i){leftBorderSum += a[i];if (leftBorderSum > maxLeftBorderSum)maxLeftBorderSum = leftBorderSum;}int maxRightBorderSum = 0, rightBorderSum = 0;for (int j = center + 1; j <= right; ++j){rightBorderSum += a[j];if (rightBorderSum > maxRightBorderSum)maxRightBorderSum = rightBorderSum;}int maxSum1 = maxLeftSum > maxRightSum ? maxLeftSum : maxRightSum;return max(maxSum1, maxLeftBorderSum + maxRightBorderSum);}int maxSubSum3(const vector &a){return maxSumRec(a, 0, a.size() - 1);}//O(N)逆天了int maxSubSum4(const vector &a){//任何负值不可能是最大子序列的开头int maxSum = 0, thisSum = 0;for (int i = 0; i < a.size(); ++i){thisSum += a[i];if (thisSum > maxSum)maxSum = thisSum;else if (thisSum < 0)thisSum = 0;}return maxSum;}int main(){vector a = { 4,-3,5,-2,-1,2,6,-2 };cout << maxSubSum1(a) << endl;cout << maxSubSum2(a) << endl;cout << maxSubSum3(a) << endl;cout << maxSubSum4(a) << endl;system("pause");
算法4是许多聪明算法的典型,它只对数据进行一次扫描,一旦a[i]被读入并被处理,就不再需要被记忆。在任意时刻,算法都能对它已经读入的数据给出子序列问题的正确答案。(联机算法(on-line algorithm),ps:仅需要常量空间并以线性时间与线性时间运行的算法几乎是完美的算法,我不造哦~)
有了最大子序列和的问题就有了最小子序列和, 照葫芦画瓢,好的算法你不用,我也很绝望啊~
int minSubSum4(const vector&a){int minSum = 0, thisSum = 0;for (int i = 0; i < a.size(); ++i){thisSum += a[i];if (thisSum < minSum)minSum = thisSum;else if (thisSum > 0)thisSum = 0;}return minSum;}
然后是最小正子序列和:
我成为我渣了,只想到了O(N^2)...
int main(){vectora = { 4,-3,5,-2,-1,2,6,-2 };//如下为算法int minSum = a[0];for (int i = 0; i != a.size(); ++i) {int thisSum = 0;for (int j = i; j != a.size(); ++j) {thisSum += a[j];if (minSum > thisSum && thisSum > 0)minSum = thisSum;}}cout << minSum;system("pause");}
具体是 对累计的和排序,然后对应出索引,找出可以成为序列的索引即可,注意对于相同的大小数据索引要一致
struct item {int index;int value;};bool cmp(item &a, item &b){//相同的值,让其索引为小的,否则就不是之比较相邻两个数的索引那么简单了if (a.value == b.value)a.index = b.index = a.index < b.index ? a.index : b.index;return a.value < b.value;}void minPSubSum(const vector&a){vector - b;item temp;int thisSum = 0;//所选序列为(x,y]temp.index = 0;temp.value = 0;b.push_back(temp);for (size_t i = 0; i < a.size(); ++i){thisSum += a[i];temp.value = thisSum;temp.index = i+1;b.push_back(temp);}sort(b.begin(), b.end(), cmp);int minPSum = b.rbegin()->value;for (size_t j = 0; j < b.size() - 1; ++j){if (b[j].index < b[j + 1].index){thisSum = b[j + 1].value - b[j].value;if (thisSum < minPSum)minPSum = thisSum;}}cout << minPSum<
a = { 4,-3,5,-2,-1,2,6,-2 };vector b = { 4, 0, 4, 1, -1 };minPSubSum(a);minPSubSum(b);system("pause");}
最大子序列乘积:
这个是没想出来,但是看到了这个公式,就秒懂了,瞬间感触也很多,对自己渣,对别人的强,以及那么多时间的停滞不前
i=1 --->>size()-1
max(a[i], maxArray[i - 1] * a[i], minArray[i - 1] * a[i]);
min (a[i], maxArray[i - 1] * a[i], minArray[i - 1] * a[i]);
int max(int a, int b, int c){int max = a;if (b > max)max = b;if (c > max)max = c;return max;}int min(int a, int b, int c){int min = a;if (b < min)min = b;if (c < min)min = c;return min;}void maxPlus(const vector&a){int maxValue= a[0];vector maxArray;maxArray.push_back(maxValue);vector minArray{ maxArray };for (size_t i = 1; i < a.size(); ++i){ //算法的精髓maxArray.push_back(max(a[i], maxArray[i - 1] * a[i], minArray[i - 1] * a[i]));minArray.push_back(min(a[i], maxArray[i - 1] * a[i], minArray[i - 1] * a[i]));if (maxArray.back() > maxValue)maxValue = maxArray.back();} cout << maxValue << endl;}int main(){vector a = { 4,-3,5,-2,-1,2,6,-2 };vector b = { 4, 0, 4, 1, -1 };maxPlus(a);maxPlus(b);system("pause");}
to be continue!!!
阅读全文
0 0
- 最大序列和问题
- 最大序列和问题
- 最大和子序列问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题~~
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- 最大子序列和问题
- Android电话响铃、接听、挂断状态
- tensorflow 学习之 cifar_10 模型定义(补)
- linux下安装jdk和tomcat
- Android加密已有的sqlite数据库---sqlcipher
- Redis-Java客户端Jedis
- 最大序列和问题
- Lua 函数
- Android:如何快速对系统重启问题进行归类
- 一般线性模型、混合线性模型、广义线性模型
- 解决ueditor百度富文本编辑器图片可以上传但是在线管理图片无法显示
- jmeter与session(2)
- 乐曲创作
- 调用Python的print函数出问题
- 淘宝开店考试试题以及50题答案