您的位置:首页 > 其它

算法 第二章 时间复杂度与空间复杂度

2017-12-01 08:12 465 查看
时间复杂度定义:

进行算法分析时:

所有语句在一起的总的操作T(n)是关于数据规模n的一个函数

进而T(n)随着n的变化情况确定T(n)的数量级

算法的时间复杂度,记作T(n)= O(f(n))

它表示随着数据规模n的增大,算法执行时间的增长率与f(n)的增长率

f(n)是数据规模n的一个函数

这样用O来体现算法时间复杂度的方法,叫做大O记法。

随着数据规模n的增大,T(n)增长最为缓慢的的算法叫做最优算法

例如,O记法可以有这样的表示方法: O(1) O(n) 或者O(n^2)的表示方法



那么如何分析算法的时间复杂度呢? -> 如何推导大O的阶呢?

用常数1取代运行时间中所有的加法常数 -> 例如3条指令+8次cout指令 加在一起,其实就是1

修改后的运行次数函数中,只保留最高次项

如果最高阶项存在而且不是1,去除与这个项相乘的常数,例如3n^2 -> O(n^2)

最后得到的结果就是大O阶,也就是时间复杂度

//常数阶     ->  O(1)
cout <<"xiaohan-xiaohan-xiaohan"<<endl;
cout <<"xiaohan-xiaohan-xiaohan"<<endl;
cout <<"xiaohan-xiaohan-xiaohan"<<endl;
cout <<"xiaohan-xiaohan-xiaohan"<<endl;
cout <<"xiaohan-xiaohan-xiaohan"<<endl;
cout <<"xiaohan-xiaohan-xiaohan"<<endl;
return 0;


//线性阶     ->   O(n)
//一般来说就是单个嵌套loop,不是for+for这种 就是线性阶
for(int i=0 ;i<n,i++){
...
}
//以上的代码,因为循环体中代码执行n次,因此时间复杂度为O(n)


//平方阶      -> O(n^2)
for (int a=0;a<n;a++){
for (int b=0;b<n;b++){
...
}
}


//这样的算法时间复杂度是多少呢?
for (int a=0;a<n;a++){
for (int b=a;b<n;b++){
...
}
}


i=0时,内循环执行了n次,i=1时,内循环执行了n-1次….. i=n-1时,内循环执行了1次

总的执行次数为 : n+(n-1)+(n-2)+…… = n(n+1)/2

首先没有常数

第二条,只保留最高次项,因此n/2忽略不计

第三条,最高阶前面的系数忽略不计

O(n^2)

这样的函数,要运算多少次以后退出呢?

//对数阶
while(i<n){
i = 2*i;
}


假设运行x次,满足大于等于n的要求

-> 由于已经满足条件,终止循环,运行了x次

-> 也就是说要乘上x遍2满足推出循环的条件

2^x = n -> x=log(2)n,因此时间复杂度为O(log(2)n)

for (int i=0 ; i<n;i++){
function(i)                    // 这里的时间复杂度是n
}
function(int i){
cout << i << endl;         // 这里的时间复杂度是1
}                                     -> 总体的时间复杂度是O(n)

for (int i=0 ; i<n;i++){
function(i)                    // 这里的时间复杂度是n
}
function(int i){
for(int y=i;y<n;y++)         // 这里的时间复杂度是n
}                                      -> 总体的时间复杂度是O(n^2)


除此之外,运算次数为n*log(n)的运算里,O是满足n * log(n)阶

还有的类型满足2^n一类的指数阶





Summary

(1).一个规则是到底要运行多少次函数才会终止

(2).区别是有的已经写明白了跟数据规模n之间的关系,例如常规for循环

(3).有的也只是要计算一下运行次数跟n之间的关系,或是直接求或是列简单方程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: