Loading

数据结构算法复杂度详解

算法复杂度问题

引例

第一种算法:(1+(n+1)+n)=2n+2次

int i,sum=0,n=100;      //执行1次
for(i=1;i<=n;i++){      //   执行n+1词
    sum+=i;             //执行n次
}

第二种算法: 1+1=2次

int sum=0,n=100;        //执行1次
sum=(1+n)*n/2;          //执行1次

如果我们把循环看作一个整体,忽略头尾判断的开销,那么这两个算法就是n和1的差距;
算法的复杂度,我们侧重的是研究算法随着输入规模的扩大增长量的一个抽象,而不是精确的定位执行了多少次;

列:

int i,j,x=0,sum=0,n=100;
for(i=1;i<=n;i++){      //执行n+1次
    for(j=1;j<=n;j++){  //当外层i每执行1次,内层j执行n+1次
        x++;            //执行n次
        sum=sum+x;
    }
}

此算法的复杂度就为\(n^{2}\),也就是\(100^2\)次;

我们在分析算法的运行时间时,重要的是把基本操作的数量和输入模式关联起来。

时间复杂度的定义: 在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,进而分析T(n)随n的变化情况确定T(n)的数量级。
算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。
它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。

通用攻略:

用常数1取代运行时间中的所有加法常数。
在修改后的运行次数函数中,只保留最高阶项。
如果最高阶项存在且不是1,则除去与这个项相乘的常数。
得到的最后结果就是大O阶。


常数阶

int sum=o,n=100;
printf("第一条");
printf("第二条");
printf("第三条");
printf("第四条");
printf("第五条");
printf("第六条");
sum = (i+1)*n/2;    //只有这一句影响了n

因为T(n)是关于问题规模n的函数,所以时间复杂度为:O(1)


线性阶

int n=100;      
for(int i=1;i < n;i++){     
    printf("hello guys");   //执行n次          
}

因为循环体中的代码需要执行n次,所以时间复杂度为:O(n)


平方阶(1)

int n=100;
for(int i=0;i < n;i++){         //执行n次
    for(int j=0;j < n;j++){     //执行n*n次
        printf("hello guys");
    }
}

因为循环体中的代码需要执行n*n次,所以时间复杂度为:O(\(n^{2}\))


平方阶(2)

int n=100;
for(int i=0;i< n;i++){          //执行n次
    for(int j=i;j< n;j++){      //当i=n时,j执行n-1次
        printf("hello guys");
    }
}

分析:

内循环总的执行次数应该是:
\(-n+(n-1)+(n-2)+...+1=\frac{n(n+1)}{2}\)
\(\frac{n(n+1)}{2}=\frac{n^2}{2}+\frac{n}{2}\)

根据大O攻略:
第一条忽略,因为没有常数相加。
第二条只保留最高项,所以\(\frac{n}{2}\)去掉。
第三条,去除与最高项相乘的常数,最终得O(\(n^{2}\))。


对数阶

int n=100;
while(int i<n){
    i=i*2;
}

由于\(2^{x}=n\)得到\(x=\log_2^{n}\),所以,这个循环的时间复杂度为O(\(\log{n}\))。


函数时间复杂度分析

int n=100;
for(int i=0;i< n;i++){
    function(i);
}
void function(int count){
    printf("hello guys");
}

函数的复杂度是O(1),而for循环的调用,所以时间复杂度是O(n)。

int n++;
function(n);

for(int i=0;i< n;i++){
    function(i);
}
for(int i=0;i< n;i++){
    for(j=i;j< n;j++){
        printf("hello guys");
    }
}
void function(int count){
    printf("hello guys");
}

\(1\)+\(1\)+\(n\)+\(n^{2}\)=O(\(n^{2}\))

总结:

O(1) < O(\(log{n}\)) < (n) < O(\(nlog{n}\)) < O(\(n^2\)) < O(\(n^3\)) < O(\(2^n\)) < O(\(n!\)) < O(\(n^n\))

posted @ 2020-03-26 12:26  平头猿小哥  阅读(428)  评论(0编辑  收藏  举报