我们知道算法本身是为了解决某个问题而设计的,而对于同一个问题往往会存在多种解决算法,所以,如何去衡量算法的效率,是非常重要的问题。
一般算法的效率是通过时间复杂度和空间复杂度两个方面来度量的。
时间复杂度(Time Complexity)它描述该算法的运行时间,本质是一个函数,时间复杂度常用大O符号表述, 这种表示方法我们称为「 大O符号表示法」,又称为渐进符号,是用于描述函数渐进行为的数学符号。
算法中基本操作重复执行的次数是问题规模 n 的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f (n)的极限值为不等于零的常数,则称 f(n) 是 T(n) 的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
常数阶 O(1)
线性阶 O(n)
平方阶 O(n2)
立方阶 O(n3)
对数阶 O(Log2n)
n倍对数阶 O(nLog2n)
表示该算法的执行时间(或执行时占用空间)总是为一个常量,不论输入的数据集是大是小,只要是没有循环等复杂结构,那这个代码的时间复杂度就都是 O(1)
例如:
int sum(int a ,int b)
{int c = a+b;return c;
}
不论 a,b 的值是多少, sum 算法的复杂度占用的时间都是确定的
表示一个算法的性能会随着输入数据的大小变化而线性变化
例如:
int sum(int n)
{int c=0;for(int i=0;i
这里当 n = 1 和 n = 100000 很明显时间会不同,并且是线性变化的。
表示一个算法的性能会随着输入数据的大小变化而平方性变化
例如:
int sum(int n)
{int c=0;for(int i=0;i
表示一个算法的性能会随着输入数据的大小变化而立方性变化
例如:
int sum(int n)
{int c=0;for(int i=0;i
表示一个算法的性能会随着输入数据的大小变化而对数性变化
例如:
int sum(int n)
{int c=0;for(int i=0;i
表示一个算法的性能会随着输入数据的大小变化而 n * O(logN),也就是了 O(nlogn) 变化
例如:
int sum(int n)
{int c=0; for(int i=0;i
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做 S(n)=O(f(n))
常数阶O(1)
线性阶O(n)
表示该算法执行时占用空间总是为一个常量,不论输入的数据集是大是小,空间复杂度就都是 O(1)
例如:
int sum(int a ,int b)
{int c = a+b;return c;
}
不论 a,b 的值是多少, sum 算法的复杂度占用的空间都是确定的
表示一个算法的占用空间随着输入数据的大小变化而线性变化
例如:
int* allocArray(int n)
{int * arr= new int[n];return arr;
}
很明显,n越大,需要分配的内存空间就越大。
对于一个算法, 时间复杂度和空间复杂度往往是相互影响的。当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间 ,以“用空间换时间”;反之,当追求一个较好的空间复杂度时,可能会使时间复杂度的性能变差,即可能导致占用较长的运行时间。另外,算法的所有性能之间都存在着或多或少的相互影响。因此,当设计一个算法(特别是大型算法)时,要综合考虑算法的各项性能,算法的使用频率,算法处理的数据量的大小,算法描述语言的特性,算法运行的机器系统环境等各方面因素,才能够设计出比较好的算法。
下一篇:AWS白皮书 – 安全性