简单的高效算法分析初步?

来源:互联网 发布:淘宝电话卡为什么便宜 编辑:程序博客网 时间:2024/05/22 07:01
   
分析一个问题:

最大连续和的问题。给出长度为n序列A1,A2,...An求连续最大和;

对于一般的想法,可以给出下面的代码

t = 0;best = A[1];for(int i = 1; i <= n; i++)  for(int j = i ; j <= n; j++){int    sum = 0;for ( int k = i ; k <= j; k++){sum += A[K]; t++:}if(sum > best) best = sum;//更新最大值}

采用的思想:幼儿园学生思想!!!!

这种算法好想但是需要经历一个三重循环

由于进行了三重循环,时间复杂度为N的三次方

对于推算时间复杂度:

()采取上界分析,最坏的情况是什么情况?对于三重循环最多也就是每个循环都进行N次,于是就推算出时间复杂度 T(n) = O(n^3);

在这种情况下,你一定要试着优化你的算法

于是我们可以使用一些优化:

S[0]  = 0;for(int  i  = 1; i <=n; i+)  s[i]  = s[i-1] +A[i];//推进前缀  for(int i = 1; i <=n; i++)for(int j =i;  j  <=  n;  j++) best  = max(best  ,s[j]  - s[i-1]);
采用的思想:递推的思想!!!(初中生必备)

这样就可以进行一个一重循环+一个二重循环

()采用上界分析,最坏的情况也就是时间复杂度T(n) = O(n^2)

----------------------------------------------------------------------------------------------------------------------------------------------------(难度增加分割线)

使用分治法来解决问题

(1) 划分问题 : 把问题的实例划分成子问题

(2)递归求解 : 递归解决子问题

(3)合并问题 : 合并子问题得到原问题的解

划分:把序列中的元素分成元素数量尽量可能相等的两半;
递归求解:分别求出位于左半或者位于右半的最佳序列
合并:求出起点位于左半、终点位于右半的的最大连续序列,并和子问题的最优解比较
#include<bits/stdc++.h>using namespace std;int maxsum(int *s, int x, int y){    int  v,left,right,mmax;    if(y - x == 1)    {        return s[x];    }    int m = x +(y - x) /2;//尽可能中间的数    mmax = max(maxsum(s,x,m),maxsum(s,m,y));//递归求解    v =  0;    left = s[m-1];    for(int i = m-1 ; i>= x; i--)    {        left = max(left,v += s[i]);    }    v = 0;    right = s[m];    for(int i = m; i < y; i++)    {        right = max(right, v += s[i]);    }    return max(mmax,left+right);//感觉向前走???}int main(){    int n;    int s[10000];    cin>>n;    for(int i = 0 ;i < n; i++)    {        cin>>s[i];    }    int m;    m = maxsum(s,0,n);    cout<<m<<endl;    return 0;}
递归求解思想(大学生正常思维)
附上全代码!感觉就像切水出波一样,在每次切完的中间再切 这样求解时间复杂度T(n) = O(n*logn)





1 0
原创粉丝点击