时间复杂度与空间复杂度
算法的复杂度
在我们学习算法的过程中,为了衡量不同算法,我们使用复杂度来区分它们的优劣。而复杂度又分为时间和空间两个维度。
时间复杂度
时间纬度是指执行当前算法所消耗的时间,我们通常用时间复杂度来描述。
算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量。
我们一般使用大O符号表示法来表示算法的时间复杂度
常见的时间复杂度量级
- 常数阶O(1)
- 线性阶O(n)
- 对数阶O(logN)
- 线性对数阶O(nlogN)
- 平方阶O(n²)
- 立方阶O(n³)
- K次方阶O(n^k)
接下来再看一下不同的复杂度所对应的算法类型。
常数阶O(1)
let a = 1;
let b = 2;
我们假定每执行一行代码所需要消耗的时间为1个时间单位,那么以上3行代码就消耗了3个时间单位。那是不是这段代码的时间复杂度表示为O(3)呢 ?
其实不是的,因为大O符号表示法并不是用于来真实代表算法的执行时间的,它是用来表示代码执行时间的增长变化趋势的。
上面的算法并没有随着某个变量的增长而增长,那么无论这类代码有多长,即使有几万几十万行,都可以用O(1)来表示它的时间复杂度。
线性阶O(n)
for(let i = 0;i<=n;i++){
a++;
b--;
}
因为循环需要执行n次,所以循环体里的代码也需要执行n次,它消耗的时间是随着n的变化而变化的,因此这类代码都可以用O(n)来表示它的时间复杂度。
对数阶O(logN)
var a = 1;
while(a>n){
a*=2
}
设循环x次后a>n,因此x=log2^n,而在写代码时要考虑的是数据规模n对程序运行效率的影响,常数部分则忽略,同样的,如果不同时间复杂度的倍数关系为常数,那也可以近似认为两者为同一量级的时间复杂度。因此它的时间复杂度为O(logN).
线性对数阶O(nlogN)
for(let i = 0;i<=name;i++){
var a = 1;
while(a>n){
a*=2
}
}
平方阶O(n²),立方阶O(n³),K次方阶O(n^k)
for(let i = 0;i<n;i++){
for(let i = 0;i<n;i++){
...k层
}
}
有几层循环就是n的几次方
常见时间复杂度的比较
O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)
空间复杂度
类似于时间复杂度的讨论,一个算法的空间复杂度定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。
空间复杂度 O(1)
var a = 1;
var b = 2;
a++;
b--;
代码中的a,b所分配的空间都不随着处理数据量变化,因此它的空间复杂度为O(1)
空间复杂度 O(n)
var arr = []
for(let i = 0;i<=n;i++){
arr.push(i)
}
给arr分配的空间会随n的变化而变化,因此空间复杂度为O(n)