在听到这两个名词的时候,感觉十分的高大上,其实很好理解
通俗讲
时间复杂度指的是一个算法执行所耗费的时间
空间复杂度指运行完一个程序所需内存的大小
复杂度的表现形式T(n) = O(f(n)),这个就是大O表示法,其中的T代表的是算法需要执行的总时间或者算法需要的总空间,f(n)表示的是代码执行的总次数
时间复杂度
let i = 1
i++ // 执行1次
i++ // 执行2次
i++ // 执行3次
console.log(i)
上述代码在执行的时候,它消耗的时间并不随着某个变量的增长而增长,那么无论这类代码有多长,即使有几万几十万行,都可以用O(1)来表示它的时间复杂度
for(i=1; i<=n; ++i)
{
i++ // 执行n次
}
这段代码执行的次数完全由变量n来控制,所以是O(n)
let i = 1;
while(i<n)
{
i = i * 2;
}
看执行次数最多的代码,就是while循环里面的那句代码 i = i * 2,就是2的k次方 =n,就是k=logn,
就是O(logn)
for (var i = 0; i < n; i++) { // 这里执行了n次
for (var j = 0; j < n; j++) { // 这里执行了n*n次
item = item +i +j; // 这里执行了n*n次
}
}
嵌套了两层for循环,就是O(n²)
function go(n) {
var item = 0; //这里执行了一次
for (var i = 0; i < n; i++) { // 这里执行了n次
for (var j = 0; j < n; j++) { // 这里执行了n*n次
item = item +i +j; // 这里执行了n*n次
}
}
return item; // 这里执行了一次
}
因此上面这段代码是 1+n+nn2+1=2+n+2n²
也就是说 T(n) = O(f(2 + n + 2n²))
但是由于时间复杂度参考的是代码执行时间的趋势,因此当n规模比较大的时候,常量起不到决定性的作用,因此这个时候我们忽略这些常量。(n相比较于n²,也相当于是常量)
因此这里的例子,只看最大量级的循环就可以了,它的时间复杂度是 T(n) = O(n²)
for(m=1; m<n; m++)
{
i = 1;
while(i<n)
{
i = i * 2;
}
线性对数阶O(nlogN) 其实非常容易理解,将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logN),也就是了O(nlogN)。
空间复杂度
let i = 1;
let j = 2;
++i;
j++;
代码中的 i、j、m 所分配的空间都不随着处理数据量变化,因此它的空间复杂度 S(n) = O(1)
var arr = Array(n);
上面代码中创建了一个n长度的数组,数组的长度(内存开销)取决于n,因此空间复杂度是 O(n)
假如 是二维数组的话,就是O(n²),因为二维数组分行和列,都是n,就是n*n
假如是成指数级的提升这种 就属于不好的算法了.
这是当初面试的时候,面试官问了菲波那切数列,然后让写一个函数,当然是想了一个最简单的方式,
function Fibonacci(n) {
if (n <= 1 ) {
return n;
} else {
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
}
这样写会出现浏览器假死现象,一直在开辟空间
然后面试官就问了一个时间复杂度和空间复杂度的问题