最大子序列和的四种求解算法及其时间比较
来源:互联网 发布:编程教育 编辑:程序博客网 时间:2024/05/21 07:04
1、T(N)=O(N^3)
__int64 algorithm1(__int64 a[],__int64 n) //T(N)=O(N^3){ __int64 MaxSum = 0; __int64 ThisSum; for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字 { for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字 { ThisSum = 0; //PS:第一轮循环k从0->0,0->1,0->2...0->n //PS:第二轮循环k从1->1,1->2,1->3...1->n //PS:第K轮循环k从k->k,k->k+1,k->k+2...k->n //PS:这样就遍历完序列中所有子序列的可能性 for(__int64 k = i; k <= j; k++) //从i开始到j的数字相加 ThisSum += a[k]; if(ThisSum > MaxSum) //大于最大子序列之和则替换 MaxSum = ThisSum; } } return MaxSum;}
2、T(N)=O(N^2)
__int64 algorithm2(__int64 a[],__int64 n) //T(N)=O(N^2){ __int64 MaxSum = 0; __int64 ThisSum; for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字 { ThisSum = 0; //PS:第一轮j从0->n,每循环一次,判断一次 //PS:第二轮j从1->n,每循环一次,判断一次 //PS:第J轮j从j->n,每循环一次,判断一次 //PS:这样就遍历完序列中所有子序列的可能性 for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字 { ThisSum += a[j]; if(ThisSum > MaxSum) //大于最大子序列之和则替换 MaxSum = ThisSum; } } return MaxSum;}
3、T(N)=O(NlogN),底数为2
PS:用分治法,先将原序列分成相似的两个子序列,这样可以得出一个结论,
那就是最大子序列和要不在左子序列中,要不在右子序列中,要不在左子序列和右子序列的连接处
对左子序列递归求最大序列和,对右子序列求最大序列和,再将左右子序列连接起来,求连接处的最大序列和
最后比较就能求出整体最大序列和
__int64 MaxSubSum(__int64 a[],__int64 Left,__int64 Right){ __int64 Center; //中间元素 __int64 MaxLeftSum,MaxRightSum; //左右子序列最大序列和 __int64 MaxLeftBorderSum,MaxRightBorderSum; //左右边界最大序列和 __int64 LeftBorderSum,RightBorderSum; //左右边界序列和 if(Left == Right) //递归出口 if(a[Left] > 0) //当a[i]>0时,返回该元素 return a[Left]; else //否则返回0 return 0; Center = (Left + Right) / 2; MaxLeftSum = MaxSubSum(a,Left,Center); //递归求解左子序列 MaxRightSum = MaxSubSum(a,Center + 1,Right); //递归求解右子序列 MaxLeftBorderSum = 0; LeftBorderSum = 0; for(__int64 i = Center; i>= Left; i--) //求左边界最大序列和 { LeftBorderSum += a[i]; if(LeftBorderSum > MaxLeftBorderSum) MaxLeftBorderSum = LeftBorderSum; } MaxRightBorderSum = 0; RightBorderSum = 0; for(__int64 i = Center + 1; i <= Right; i++) //求右边界最大序列和 { RightBorderSum += a[i]; if(RightBorderSum > MaxRightBorderSum) MaxRightBorderSum = RightBorderSum; } return max(max(MaxLeftSum,MaxRightSum),MaxLeftBorderSum+MaxRightBorderSum); //返回整体最大序列和}__int64 algorithm3(__int64 a[],__int64 n) //T(N)=O(NlogN),底数为2{ return MaxSubSum(a,0,n - 1);}
4、T(N)=O(N)
推荐用这种算法
__int64 algorithm4(__int64 a[],__int64 n) //T(N)=O(N){ __int64 ThisSum = 0; __int64 MaxSum = 0; for(int i = 0; i < n; i++) //i从零开始到最后一个数字 { ThisSum += a[i]; if(ThisSum < 0) //当a[j]+...+a[i] < 0,则舍弃i之前的所有序列,从i后继续累加 ThisSum = 0; if(ThisSum > MaxSum) //求出当前序列的最大子序列和 MaxSum = ThisSum; } return MaxSum;}
5、数量级及其时间比较表格
6、源代码及其测试数据
#include <iostream>#include <fstream>#include <cstdlib>#include <ctime>using namespace std;__int64 algorithm1(__int64 a[],__int64 n) //T(N)=O(N^3){ __int64 MaxSum = 0; __int64 ThisSum; for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字 { for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字 { ThisSum = 0; //PS:第一轮循环k从0->0,0->1,0->2...0->n //PS:第二轮循环k从1->1,1->2,1->3...1->n //PS:第K轮循环k从k->k,k->k+1,k->k+2...k->n //PS:这样就遍历完序列中所有子序列的可能性 for(__int64 k = i; k <= j; k++) //从i开始到j的数字相加 ThisSum += a[k]; if(ThisSum > MaxSum) //大于最大子序列之和则替换 MaxSum = ThisSum; } } return MaxSum;}__int64 algorithm2(__int64 a[],__int64 n) //T(N)=O(N^2){ __int64 MaxSum = 0; __int64 ThisSum; for(__int64 i = 0; i < n; i++) //i从零开始到最后一个数字 { ThisSum = 0; //PS:第一轮j从0->n,每循环一次,判断一次 //PS:第二轮j从1->n,每循环一次,判断一次 //PS:第J轮j从j->n,每循环一次,判断一次 //PS:这样就遍历完序列中所有子序列的可能性 for(__int64 j = i; j < n; j++) //j从i开始到最后一个数字 { ThisSum += a[j]; if(ThisSum > MaxSum) //大于最大子序列之和则替换 MaxSum = ThisSum; } } return MaxSum;}//PS:用分治法,先将原序列分成相似的两个子序列,这样可以得出一个结论,//那就是最大子序列和要不在左子序列中,要不在右子序列中,要不在左子序列和右子序列的连接处//对左子序列递归求最大序列和,对右子序列求最大序列和,再将左右子序列连接起来,求连接处的最大序列和//最后比较就能求出整体最大序列和__int64 MaxSubSum(__int64 a[],__int64 Left,__int64 Right){ __int64 Center; //中间元素 __int64 MaxLeftSum,MaxRightSum; //左右子序列最大序列和 __int64 MaxLeftBorderSum,MaxRightBorderSum; //左右边界最大序列和 __int64 LeftBorderSum,RightBorderSum; //左右边界序列和 if(Left == Right) //递归出口 if(a[Left] > 0) //当a[i]>0时,返回该元素 return a[Left]; else //否则返回0 return 0; Center = (Left + Right) / 2; MaxLeftSum = MaxSubSum(a,Left,Center); //递归求解左子序列 MaxRightSum = MaxSubSum(a,Center + 1,Right); //递归求解右子序列 MaxLeftBorderSum = 0; LeftBorderSum = 0; for(__int64 i = Center; i>= Left; i--) //求左边界最大序列和 { LeftBorderSum += a[i]; if(LeftBorderSum > MaxLeftBorderSum) MaxLeftBorderSum = LeftBorderSum; } MaxRightBorderSum = 0; RightBorderSum = 0; for(__int64 i = Center + 1; i <= Right; i++) //求右边界最大序列和 { RightBorderSum += a[i]; if(RightBorderSum > MaxRightBorderSum) MaxRightBorderSum = RightBorderSum; } return max(max(MaxLeftSum,MaxRightSum),MaxLeftBorderSum+MaxRightBorderSum); //返回整体最大序列和}__int64 algorithm3(__int64 a[],__int64 n) //T(N)=O(NlogN),底数为2{ return MaxSubSum(a,0,n - 1);}__int64 algorithm4(__int64 a[],__int64 n) //T(N)=O(N){ __int64 ThisSum = 0; __int64 MaxSum = 0; for(int i = 0; i < n; i++) //i从零开始到最后一个数字 { ThisSum += a[i]; if(ThisSum < 0) //当a[j]+...+a[i] < 0,则舍弃i之前的所有序列,从i后继续累加 ThisSum = 0; if(ThisSum > MaxSum) //求出当前序列的最大子序列和 MaxSum = ThisSum; } return MaxSum;}__int64 Random(__int64 m,__int64 n) //指定范围内随机数{ __int64 pos,dis; if(m == n) //m=n则表示范围内只有一个数字 { return m; } else if(m > n) //m>n则说明取[m,n]区间内数字 { pos = n; dis = m - n + 1; return rand() % dis + pos; } else //m>n则说明取[n,m]区间内数字 { pos = m; dis = n - m + 1; return rand() % dis + pos; }}void MakeRandomSequences(__int64 m,__int64 n,__int64 num) //产生随机序列{ ofstream filerandom("G:\\sequences.txt"); srand((int)time(NULL)); //根据时间产生相应种子值 for(int i=0 ; i < num; i++) { filerandom << Random(m,n) <<" "; if(!((i + 1) % 10)) //数据量逢十换行 filerandom << endl; } filerandom.close();}int main(){//测试数据// __int64 a[] = {4,-3,5,-2,-1,2,6,-2};// __int64 n = 8;// cout << algorithm1(a,n) << endl;// cout << algorithm2(a,n) << endl;// cout << algorithm3(a,n) << endl;// cout << algorithm4(a,n) << endl;// MakeRandomSequences(-1000,1000,100000); //产生随机序列 __int64 a[200000]; __int64 n = 0; ifstream filesequ("G:\\sequences.txt"); if(!filesequ.is_open()) //打开失败处理 { cout<<"Error opening file"; return -1; } while(!filesequ.eof()) { filesequ >> a[n++]; } filesequ.close();//PS:测试只需要把调用算法注释去掉// cout << algorithm1(a,n) << endl;// cout << algorithm2(a,n) << endl;// cout << algorithm3(a,n) << endl; cout << algorithm4(a,n) << endl; return 0;}
0 0
- 最大子序列和的四种求解算法及其时间比较
- 求最大子序列和的四种经典方法及其算法时间复杂度分析
- 求解最大子序列和问题的线性时间算法
- 数组连续子序列的最大的和-四种算法,四种时间复杂度
- 数组连续子序列的最大的和;四种算法,四种时间复杂度
- 求解最大子序列算法及比较
- 求解最大子列和问题的四种算法
- 最大子序列和问题的四种算法
- 最大子序列和的四种算法
- 最大子序列和的四种算法之讲解
- 算法笔记1-最大子序列和问题的求解
- 【数据结构与算法】最大子序列和问题的求解
- 最大连续子序列的四种求解方法
- 最大子列和的四种算法比较
- 最大子序列和的线性算法及其它算法
- 最大子序列和的线性算法及其它算法
- 连续子数组最大和或最大子段和的求解算法及其正确性
- 最大子序列和问题的求解
- HTML5基础03----HTML5元素简介及使用方法
- WebRTC
- HDU3466
- 每天一个Linux命令-10(Linux find xargs详解)
- MapReduce的KeyValueTextInputFormat
- 最大子序列和的四种求解算法及其时间比较
- win7CMD route配置内外网双网卡操作
- HDU5308-脑补-对拍
- C语言结构体
- LTE调度算法(下行)
- bzoj3172: [Tjoi2013]单词
- C语言统计不同字符的字数
- Android 多分辨率自适应总结
- Opengl Lesson 1 心形曲线