时间复杂度与空间复杂度
转载自:http://www.cnblogs.com/xiu619544553/tag/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/
高级语言编写的程序在计算机上运行时所消耗的时间取决于下列因素:
1.算法采用的策略,方案;
2.编译产生的代码质量(编译器);
3.问题的输入规模(输入量的多少);
4.机器执行指令的速度。
研究算法的复杂度,侧重的是研究算法随着输入规模扩大增大量的一个抽象!!
一、算法时间复杂度概念
- 常数阶:
1 int sum = 0, n = 100; 2 printf("I'll move on.\n"); 3 printf("I'll move on.\n"); 4 printf("I'll move on.\n"); 5 printf("I'll move on.\n"); 6 printf("I'll move on.\n"); 7 printf("I'll move on.\n");
上面代码的大O阶并不是O(8),按照概念"T(n)是关于问题规模n的函数来说"、"1)"证明,O(1)才是正确答案;
- 线性阶:
一般含有非嵌套循环涉及线性阶,线性阶就是随着问题规模n的扩大,对应计算次数呈直线增长。
1 int i, sum = 0, n = 100; 2 3 for (i = 0; i < n; i ++ ) { 4 sum += i; 5 }
上面这段代码,它的循环的时间复杂度为O(n),因为循环体中代码需要执行n次。
- 平方阶:
1 int i, j, n = 100; 2 for (i = 0; i < n; i ++ ) { 3 for (j = 0; j < n; j ++) { 4 printf("I'll move on.\n"); 5 } 6 }
n等于100,也就是说外层循环每执行一次,内层循环就执行100次,那总共想要从这两个循环出来,需要执行100*100次,也就是n的平方。所以这段代码的复杂度为 O(n^2)。
如果三个嵌套循环,那就是n^3。所以我们就可以得出结论:循环的时间复杂度等于循环体的复杂度乘以该循环运行的次数。
1 int i, j, n = 100; 2 for (i = 0; i < n; i ++ ) { 3 for (j = i; j < n; j ++) { // 此处j=i 4 printf("I'll move on.\n"); 5 } 6 }
分析该代码,最后执行的次数为:n * (n + 1) /2 = n^2/2 + n/2;
使用推导大O阶的攻略,第一条忽略(没有常数相加)。第二条只保留最高项(去掉)。第三条,去除与最高项相乘的常数,最终得O(n^2)。
- 对数阶:
1 int i = 1, n = 100; 2 while (i < n) { 3 i = i * 2; 4 } 5 printf("%d", i);
假设有x个2相乘后大于或等于n,则退出循环。
得到 2^x = n → x = log(2)n,所以这个循环的时间复杂度为 O(logn)。
函数调用的时间复杂度分析:
1)
1 // 大O阶为 O(1) 2 void function(int count) { 3 printf("%d", count); 4 } 5 6 7 int main(int argc, const char * argv[]) { 8 9 // 大O阶为O(n) 10 int i, n = 100; 11 for (i = 0; i < n; i ++) { 12 function(i); 13 } 14 15 return 0; 16 }
2)
1 // 大O阶为 O(n) 2 void function(int count) { 3 // 大O阶为O(n) 4 int j, n = 100; 5 for (j = 0; j < n; j ++) { 6 printf("%d", j); 7 } 8 } 9 10 int main(int argc, const char * argv[]) { 11 12 // 大O阶为O(n^2) 13 int i, n = 100; 14 for (i = 0; i < n; i ++) { 15 function(i); 16 } 17 18 return 0; 19 }
常见的时间复杂度:
常用的时间复杂度所耗费的时间从小到大依次是:
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n).
最坏情况与平均情况:
平均运行时间是期望的运行时间。
最坏运行时间是一种保证。在应用中,这是一种最重要的需求,通常除非特别指定,我们提到的运行时间都是最坏情况的运行时间。
二、算法的空间复杂度
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。比如直接插入排序的时间复杂度是O(n^2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。
通常所说的复杂度指的是时间复杂度!