衡量一个算法的好坏一般由两个维度来表示。时间复杂度和空间复杂度。
时间复杂度:表示算法的运行时间,T(n) = O(f(n))
空间复杂度:表示算法的暂用内存空间,S(n) = O(1)
- 时间复杂度
首先要说的这里的运行时间并不是指计算程序具体运行的时间,而是算法执行语句的次数。
for(i=1; i<=n; i++)
{
j = i;
j++;
}
忽略不同的机器配置和外界因素,上面例子运行第一遍的时间为1个单位时间,那么最后决定他的就是这个n,时间复杂度为时间复杂度表示是O(n)。
n=10;
for(i=1;i<=n;i++){
j = i;
j++;
}
无论代码执行了多少行,只要是没有循环等复杂结构只要是没有循环等复杂结构,那这个代码的时间复杂度就都是O(1)。
该算法执行次数是10,是一个常数,用时间复杂度表示是O(1)。
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
m=j+i;
}
}
该算法for循环,最外层循环每执行一次,内层循环都要执行n次,执行次数是根据n所决定的,时间复杂度是O(n^2),如果我将最内层的n换成m,那此算法的时间复杂度就是 O(m*n)。,如果内层循环在某种场景一次就跳出,其实也可以退化成o(n), 通常我们计算时间复杂度都是计算最多情况.由此类推,如果是三层循环,最大时间复杂度就是 O(n^3)。
int i = 1;
while(i<n)
{
i = i * 2;
}
2 的 x 次方等于 n,那么x = log2n,此算法的时间复杂度就是O(logn);
总结:
常见的时间复杂度有:
常数阶O(1),
对数阶O(log2 n),
线性阶O(n),
线性对数阶O(n log2 n),
平方阶O(n^2),
立方阶O(n^3)
k次方阶O(n^K),
指数阶O(2^n)。
随着n的不断增大,时间复杂度不断增大,算法花费时间越多。
计算方法
①选取相对增长最高的项
②最高项系数是都化为1
③若是常数的话用O(1)表示
- 空间复杂度
空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度。
a=1;
b=2;
c=a+b;
代码中的 a、b、c所分配的空间都不随着处理数据量变化,因此它的空间复杂度 S(n) = O(1).
fun(n)
{
k=10;
if(n==k)
return n;
else
return fun(++n);
}
递归实现,调用fun函数,每次都创建1个变量k。调用n次,空间复杂度O(n*1)=O(n)。
总结:
①忽略常数,用O(1)表示
②递归算法的空间复杂度=递归深度N*每次递归所要的辅助空间
③对于单线程来说,递归有运行时堆栈,求的是递归最深的那一次压栈所耗费的空间的个数,因为递归最深的那一次所耗费的空间足以容纳它所有递归过程。
对于一个算法来说,空间复杂度和时间复杂度往往是相互影响的。
当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间;反之,当追求一个较好的空间复杂度时,可能会使时间复杂度的性能变差,即可能导致占用较长的运行时间。
有时我们可以用空间来换取时间以达到目的。
- 常识