算法复杂度简介

时间复杂度,空间复杂度,大O表示法

Posted by pfan8 on July 3, 2019

前言

由于实际生产中,输入数据通常会呈现数量级的增长,为了更好的衡量算法性能对系统本身造成的影响,就要分析算法以输入数量n为衡量标准的时间开销和内存/存储开销,即所谓的时间复杂度和空间复杂度。

概念

算法的时间复杂度(Time Complexity),用来度量算法的运行时间,记作: T(n) = O(f(n))。它表示随着 输入大小n 的增大,算法执行需要的时间的增长速度可以用 f(n) 来描述。

算法的空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。比如直接插入排序的时间复杂度是O(n^2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归函数要单独开辟函数的空间,存储函数局部变量、返回值等信息。因此要尽量避免使用递归

表示方法:

  1. 大O表示法

代码的运行时间,和运行的指令次数成正比: \(T(n)=O(f(n))\)

  • T(n) 是所有代码的执行时间
  • n 表示数据规模的大小
  • f(n) 表示一行一行代码执行次数的总和 常见的大O复杂度
  1. 其他表示方法:Omega(\(\omega\))、Theta(\(\theta\))等

大O表示法最为常用,但也存在大Ω表示法和大Θ表示法等,它们的区别这篇文章描述的很清晰,在此就不赘述了

O(1):常量阶

所有的代码的执行次数是一个定值, 无论多大多小, 只要不随 n 的增大而增大, 这样的代码复杂度就是 O(1)

// O(1)
int k = 100;

// O(1)
const long long f = 10000000000000000000000000000;
for(int i = 0; i < f; ++i)
{
}

O(log n):对数阶

数据从起始状态, 以乘法的形式向上生长去接近 n, 其时间复杂度就是 O(logn) O(\log n)O(logn)

int i = 1;
while(i <= n)
	i = i * 2;

O(n):线性阶

与n成正比,自然是n层循环啦

int i = 0;
while( i < n)
	printf("%d \n",i);

O(nlog n):线性对数阶

O(nlogn) 自然就是 一段 O(logn) 的代码, loop 了 n次. 之所以将这个复合府再度单提出来, 是因为这个 O(nlogn) 复杂度很常见, 比如归并排序, 快排等等.

O(\(n^k\)):k次方阶

例如O(\(n^2\)),O(\(n^3\)),实际上就是k层循环的嵌套

O(\(2^n\)):指数阶

增长非常迅速,绝对要避免

O(n!):阶乘阶:

最恐怖的复杂度,如果你写出来这样的代码,恭喜你,向上面的时间复杂度改进吧!(捂脸)

空间复杂度

上述大O表示法的分析是以时间复杂度为例,空间复杂度则用类似的思路考虑存储空间的消耗即可。通常更关注时间复杂度,不过在一些项目中可能存在特定的要求,尽量减少存储消耗,这种时候就要考虑空间复杂度了~

参考

作者:鹅城惊喜师爷 来源:CSDN 原文:https://blog.csdn.net/baishuo8/article/details/82903000 版权声明:本文为博主原创文章,转载请附上博文链接!