算法设计与分析不定期更新的日常之最大子段和四种方法
来源:互联网 发布:全局mac认证配置 编辑:程序博客网 时间:2024/05/03 18:07
算法设计与分析不定期更新的日常之最大子段和四种方法:
代码实现如下:
#include <iostream>#include <cstdio>///最大子段和四种方法#include <cstring>using namespace std;const int maxn=100;int maxsum1(int n,int a[],int &besti,int &bestj)///超级无敌大暴力,复杂度O(n^3){ int maxx=0; for(int i=0; i<n; i++) { for(int j=i; j<n; j++) { int tmp=0; for(int k=i; k<=j; k++) { tmp+=a[k]; } if(tmp>maxx) { maxx=tmp; besti=i; bestj=j; } } } return maxx;}int maxsum2(int n,int a[],int &besti,int &bestj)///暴力,复杂度O(n^2){ int maxx=0; for(int i=0; i<=n; i++) { int tmp=0; for(int j=i; j<n; j++) { tmp+=a[j]; if(tmp>maxx) { maxx=tmp; besti=i; bestj=j; } } } return maxx;}int maxsum3(int a[],int left,int right,int &besti,int &bestj)///利用分治的方法来求解数组的最大子段和问题,时间复杂度降为O(nlogn){ if(left==right) { if(a[left]>0) { return a[left]; besti=bestj=left; } else { return 0; } } else { int sum; int mid=(left+right)/2; int besti1,bestj1,besti2,bestj2; besti1=bestj1=besti2=bestj2=0; int max1=maxsum3(a,left,mid,besti1,bestj1); int max2=maxsum3(a,mid+1,right,besti2,bestj2); int s1,s2,tmp; s1=s2=tmp=0; for(int i=mid; i>=left; i--) { tmp+=a[i]; if(tmp>s1) { s1=tmp; besti=i; } } tmp=0; for(int j=mid+1; j<=right; j++) { tmp+=a[j]; if(tmp>s2) { s2=tmp; bestj=j; } } sum=s1+s2; if(max1>sum) { sum=max1; besti=besti1; bestj=bestj1; } else if(max2>sum) { sum=max2; besti=besti2; bestj=bestj2; } // cout<<"besti="<<besti<<" bestj="<<bestj<<endl; return sum; }}int maxsum4(int a[],int n,int *c,int &d)///利用动态规划的方法来求解最大子段和,复杂度会更低,变为O(n){ int b[100]; memset(b,0,sizeof(b)); b[-1]=0; int sum=0;///采用利用c[]数组和最大子段和的最右边界d返回最大子段和下标的方法(同样可以利用b[]数组可以返回) for(int i=0;i<n;i++) { if(b[i-1]>0) { b[i]=b[i-1]+a[i]; c[i]=1; } else { b[i]=a[i]; c[i]=2; } if(b[i]>sum) { sum=b[i]; d=i; } //cout<<"sum="<<sum<<endl; } return sum;}void output1(int a[],int d,int c[])///正序输出{ int k=0; for(int i=d;i>=0;i--) { if(c[i]==2) { k=i; break; } } for(int i=k;i<=d;i++) { printf("%d ",a[i]); } printf("\n");}void output2(int a[],int d,int c[])///逆序输出{ int i=d; do { printf("%d ",a[i]); }while(c[i--]==1); printf("\n");}int main(){ int a[maxn]; int n; while(scanf("%d",&n)!=EOF) { for(int i=0; i<n; i++) { scanf("%d",&a[i]); } cout<<"方法1:暴力O(n^3)"<<endl; int bi1,bj1; bi1=bj1=0; int k1=maxsum1(n,a,bi1,bj1); printf("数组中的最大子段和为%d,满足最大子段和的子段是从数组中第%d个元素开始,到%d个元素结束的.\n",k1,bi1+1,bj1+1); cout<<"方法2:暴力O(n^2)"<<endl; bi1=bj1=0; int k2=maxsum2(n,a,bi1,bj1); printf("数组中的最大子段和为%d,满足最大子段和的子段是从数组中第%d个元素开始,到%d个元素结束的.\n",k2,bi1+1,bj1+1); cout<<"方法3:分治法O(nlog(n))"<<endl; bi1=bj1=0; int k3=maxsum3(a,0,n-1,bi1,bj1); printf("数组中的最大子段和为%d,满足最大子段和的子段是从数组中第%d个元素开始,到%d个元素结束的.\n",k3,bi1+1,bj1+1); cout<<"方法4:动态规划 "<<endl; bi1=bj1=0; int c[maxn]; int d; int k4=maxsum4(a,n,c,d); printf("数组中的最大子段和为%d.\n",k4); cout<<"正序输出最大子段和序列:"<<endl; output1(a,d,c); cout<<"逆序输出最大子段和序列:"<<endl; output2(a,d,c); } return 0;}
0 0
- 算法设计与分析不定期更新的日常之最大子段和四种方法
- 计算机算法设计与分析之不定期更新的日常+动态规划矩阵连乘+最长公共子序列
- 算法设计与分析之不定期更新的日常 0-1背包问题
- 算法设计与分析之不定期更新的日常3+贪心
- 算法设计与分析之-最大子段和 (分治)
- 【算法设计与分析】最大子段和问题
- 算法设计与分析——动态规划方法求解序列的连续最大子段和
- 算法分析与设计-10- 最大子段和的动态规划算法
- 算法设计与分析——动态规划方法求解序列的连续最大子段
- 求最大子序列和的四种经典方法及其算法时间复杂度分析
- 【算法设计】最大子段和问题
- 最大子序列和的四种算法之讲解
- 算法设计与分析--求最大子段和问题(蛮力法、分治法、动态规划法) C++实现
- 最大子段和四种求法
- 最大子段和四种求法
- 最大子段和几种算法
- 最大子段和算法
- 最大子段和算法
- 类和对象的基础7——友元函数和友元类
- VS2010(C++)改变对话框背景颜色
- gcc命令参数解析1
- 05-树8 堆中的路径 (25分)
- 通过CGI程序传递checkbox数据 python3
- 算法设计与分析不定期更新的日常之最大子段和四种方法
- 1079 中国剩余定理
- 【思想】思想上移●行动下移
- HDU 3078 Network LCA + 排序
- ggplot 多列bar图
- [校招准备]之:java——Object的公用方法
- Linux GCC常用命令
- 在Activity中调用finish()方法之后需要注意的事情(转)
- codeforces 126B password KMP