一、復雜度的表示方式
大O表示法,其中T代表的是算法需要執行的總時間,S表示的是算法需要的總空間
f(n)表示的是代碼執行的總次數
T(n) = O(f(n))
S(n) = O(f(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+n*n*2+1=2+n+2n²
也就是說 T(n) = O(f(2 + n + 2n²))
但是由於時間復雜度參考的是代碼執行時間的趨勢,因此當n規模比較大的時候,常量起不到決定性的作用,因此這個時候我們忽略這些常量。
因此這里的例子,只看最大量級的循環就可以了,它的時間復雜度是 T(n) = O(n²)
二、時間復雜度
a.時間復雜度的定義
首先,時間復雜度不代表代碼執行的時間,算法的時間復雜度說的是一個算法的執行時間根據規模增長的一個趨勢,而並不是代碼執行的具體時間
b.幾種常見的時間復雜度
1. O(n)
for (var i = 0; i < n; i++) { sum += i; }
這個比較容易理解,這段代碼的執行時間完全由N來控制,所以說T(n) = O(n)
2. O(1)
function total(n) { console.log('hello') }
無論怎樣,這段函數不受任何參數影響,代碼走一遍就完了,這種代碼的時間復雜度用 T(n) = O(1)
3. O(n²)
之前介紹的兩層循環的代碼,它的時間復雜度就屬性 O(n²)
另外,再舉個多塊代碼的情況下的時間復雜度計算方式
function go(i) {
var sum = 0;
for (var j = 0; j < i; j++) {
sum += i;
}
return sum;
}
function main(n) {
var res = 0;
for (var i = 0; i < n; i++) {
res = res + go(i); // 關注這里
}
}
在上邊的代碼中第二段代碼里調用了第一段代碼,
第一段代碼go: (1+ n)
第二段代碼main: (1 + n*go) = (1 + n + n * n)
因此,最后的時間復雜度是 T(n) = O(n²)
c.多塊代碼的時間復雜度
上邊舉例說明的 T(n) = O(n²),是一個函數在另一個函數里邊被調用,這種情況下是把兩個函數的時間復雜度相乘
還有另外一種情況,就是在一個函數里面有多塊代碼,但是並沒有相互調用,在這樣的情況下,我們只需要取復雜度最大的代碼塊就可以了
舉個栗子
function go(n) { for (var i = 0; i < n; i++) { for (var j = 0; j < n; j++) { console.log(1); } } for (var i = 0; i < n; i++) { console.log(2); } }
上邊這塊代碼,第一塊代碼有兩層循循環,它的復雜度是 n²;第二塊代碼,它的復雜度是 n
那么在這種情況下,當 n 接近無限大的時候,n 對整塊代碼的時間復雜度起不到決定性作用,因此在這里整塊代碼的復雜度就取起決定性作用的 n²
d.對數階和相加情況
var i = 1; while (i < n) { i = i * 10; }
在上面這段代碼中,可以看到while里面,判斷條件i每次被*10,所以導致最后循環的次數並不是n次,通過計算這個代碼的時間復雜度是 10 ^ x = n -> x = lgn
所以得出結論時間復雜度是 T(n) = O(logn)
e.其他情況
另外,還有的情況是通過改變變量會增加循環次數的,同理是增加了時間復雜度
還時間復雜度相加
function go(m, n) { for (var i = 0; i < n; i++) { console.log(1); } for (var j = 0; j < m; j++) { console.log(2); } }
上面的代碼,代碼里面有兩個循環,但是我們無法判斷n和m到底哪個大,因此在這種情況下代碼的時間復雜度是 O(m+n)
三、空間復雜度
a.空間復雜度的定義
時間復雜看的是代碼的執行時間的趨勢,那么同理的,空間復雜度就是指占用內存的趨勢
b.常見的空間復雜度
空間復雜度沒有時間復雜度那么復雜,常見的就是幾種
因為一般大家不會一直循環着聲明變量
1. O(1)
var a = 1; var b = 2; var c = 3;
2.O(n)
var arr = Array(n);
上面代碼中創建了一個n長度的數組,數組的長度(內存開銷)取決於n,因此空間復雜度是 O(n)
3.O(n²)
var arr = []; for (vra i = 0; i < n; i++) { arr[i] = []; for (var j = 0; j < n; j++) { arr[i][j] = j; } }
四、復雜度的優化
各個復雜度的曲線圖
舉個優化的例子
function go(n) {
var total = 0;
for (vra i = 1; i <= n; i++) {
total+= i;
}
return total;
}
function go2(n) {
return (1 + n) * n / 2;
}
go(1000)
go2(1000)
比較這兩個相同功能的函數的運算用時;可以體會到數學在優化算法時的重要性
另外,再舉個斐波那契的栗子
斐波那契: 就是從第三項開始依次等於前兩項的和
function Fibonacci(n) { if (n <= 1) { return n; } else { return Fibonacci(n - 1) + Fibonacci(n - 2); } } Fibonacci(10)

