算法第一个引子:求子数列的最大和
一直恐惧数据结构的某大一学生终于耐不住寂寞开始了算法的预习
先从一个最简单的开始吧
众所周知 那就是 !!求一段数列的子数列的最大和 !!
这里说4种学到的方法
从最简单的说起,那就是从i到j再用循环将每一段的和都求出来
当然这种情况在数据过大的时候,电脑会罢工(谁给我瓶脉动)
NO.4
int FindMaxSub4(int *a, int n){
int Max=0;
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
int sub=0;
for(int k=i;k<=j;k++){
sub+=a[k];
if(sub>Max) Max=sub;
}
}
}
return Max;
}
NO.3
为了让程序快一些,
聪明的前辈想到可以不用 k 的那重循环
直接在前面求出的和的基础上,添加上后面的就可以啦~
int FindMaxSub3(int *a, int n){
int Max = 0;
for(int i=0;i<n;i++){
int sub=0;
for(int j=i;j<n;j++){
sub+=a[j];
if(sub>Max) Max=sub;
}
}
return Max;
}
NO.2
在快一点的就是传说中的分治啦
这一是我从上大学以来面对黑框框这么久第一次听到这么有诗意的名字
它的原理是想将数据不断分成两半
再分别求出左半,右半,以及跨过分界线的最大值
再将他们三者比较得到最终结果
int Max3(int a,int b,int c){
return a>b?a>c?a:c:b>c?b:c;
}//用函数求出三个数的最大值
int DivideandConquer(int *a, int left, int right){
int MaxLsum,MaxRsum;
int MaxLBorderSum,MaxRBorderSum;
int LeftBorderSum,RightBorderSum;
int center,i;
//end 递归出口
if(left==right){
if(a[left]>0) return a[left];
else return 0;
}
//divide
center = (left+right)/2;
MaxLsum = DivideandConquer(a,left,center);
MaxRsum = DivideandConquer(a,center+1,right);
LeftBorderSum = 0;
MaxLBorderSum = 0;
for(i=center; i>=left; i--){
LeftBorderSum+=a[i];
if(LeftBorderSum>MaxLsum) MaxLBorderSum=LeftBorderSum;
}
RightBorderSum = 0;
MaxRBorderSum = 0;
for(i=center; i<=right; i++){
RightBorderSum+=a[i];
if(RightBorderSum>MaxRsum) MaxRBorderSum=RightBorderSum;
}
//conquer
return Max3(MaxLsum,MaxRsum,MaxLBorderSum+MaxRBorderSum);
}
int FindMaxSub2(int *a, int n){
return DivideandConquer(a, 0, n-1);
}
NO.1
最后就是最棒的算法啦!
我们叫他在线求法
因为他就是从头往后读哦
其复杂度也只有n,没有可能更快啦
他在同时更新Max和范围
当sum>Max 时,更新max
当sum<0时就可以舍弃前面的所有数啦
因为比零小还不如不加呢,哼
就是这么傲娇
int FindMaxSub1(int *a, int n){
int Max=0,num=0;
for(int i=0;i<n;i++){
num+=a[i];
if(num>Max){
Max=num;
}
else if(num<0){
num=0;
}
}
return Max;
}
这些就是学到的求子数列最大和的方法啦
看来数据结构还是有很大用的~
有没有引起你对数据结构的兴趣呢~
一起加油吧!!!