复杂度
复杂度包括时间复杂度与空间复杂度,算法中数据的存储往往并不是问题,因此算法更注重用空间换时间。本文介绍的是时间复杂度。
1.O(1)
let n; //执行一次,时间复杂度为O(1)
n+=1;//执行一次O(1)
执行次数是一个常数项时,时间复杂度就用O(1)来表示。
2.O(n)
for(let i=0;i<n;i++){ // 执行n次
console.log('...')
}
for循环的次数是随着n的变化而变化,所以为n。
我们把算法的执行次数用T(n)表示,函数执行的时间复杂度用F(n)表示。接下来引入时间复杂度:
当n>=2时,f(n)= n^2总是大于或等于 T(n+2),即F(n)=T(n),也就是说F(n)是T(n)的上界。此时我们可以用F(n)的增长速度度量T(n)的增长速度,所以说这个算法的时间复杂度是O(f(n))
3. O(logn)
let i = 1
while (i < 64) {
console.log(i);
i *= 2
}
这就是数学中所学的log函数,数学表示的话就是x=log(a)(N),即a^x=N,x就叫做以a为底N的对数。上例中用x就记做x=log(2)(N),那么这个对数x其实就是函数执行的次数,即T(n)=x。x用时间复杂度就表示为O(logn),F(n)=O(logn),即T(n)=F(n)。
4.O(n^2)
用大O表示法默认该算法所有可能最上界的最下界。
for(let i=0;i<n;i++){ // 执行n次
for(let i=0;i<n;i++){ // 执行n次
for(let i=0;i<n;i++){ // 执行n次
console.log('...')
}
}
}
T(n)=n^2,用时间复杂度就表示为F(n)=(O(n^2)),即T(n)=F(n)。那么T(n)=n^3、依次都是成立的,因为第一个F(n)用来度量T(n)是最接近的,也是最好的选择,所以为O(n^2)。
习题
如何根据函数T(n)根据函数执行次数得出事件复杂度F(n)?
常数项对函数执行时间的增长速度是没有影响的,例如T(n)=c,当c是一个常数项时:
var a = 1 // 执行一次
console.log(a) //执行一次
此时T(n)=2,函数时间复杂度表示为F(n) = O(1)
1.一个循环体的时间复杂度用O(n)来表示,循环次数用m来表示,则下面这个例子就是O(n*m)
for(let i=0;i<n;i++){ //循环次数n次
console.log(i) //时间复杂度O(1)
}
2.对于多个循环体
for(let i=0;i<n;i++){ // 执行n次
for(let i=0;i<n;i++){ // 执行n次
console.log('...') //时间复杂度为O(1)
}
}
函数时间复杂度表示为F(O* n * n * 1),即O(n^2)。
3.对于执行顺序相同的for循环或者if/else中的for循环,总时间复杂度=时间复杂度最大的那个.
// 第一部分时间复杂度为 O(n^2)
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
console.log("1");
}
}
// 第二部分时间复杂度为 O(n)
for(int j = 0; j < n; j++) {
console.log("2");
}
即都是O(n^2)。
4.求该函数的时间复杂度
let i = 1
while (i < 64) {
console.log(i);
i *= 2
}
和上述的3. O(logn)介绍相同。