前言
本筆記主要記錄如何分析、統計算法的執行效率和資源消耗。
必須學會分析復雜度分析。
李柱明博客:https://www.cnblogs.com/lizhuming/p/15487271.html
復雜度
復雜度分為:
-
時間復雜度。關聯到執行效率。
- 時間復雜度的全稱是 漸進時間復雜度,表示算法的執行時間與數據規模之間的增長關系。
-
空間復雜度。關聯到資源消耗。
- 空間復雜度全稱就是漸進空間復雜度,表示算法的存儲空間與數據規模之間的增長關系。
分析方法
大 O 復雜度表示法
先說結論:
- 大 O 復雜度表示方法只是表示一種變化趨勢。
- 忽略掉公式中的常量、低階、系數,只需要記錄一個最大階的量級就可以了。
- 多、加法和乘法規則。
例子-評估累加和的各種算法執行效率
算法 1(for 循環):
int cal(int n)
{
int sum = 0;
int i = 1;
for (; i <= n; ++i)
{
sum = sum + i;
}
return sum;
}
-
從 CPU 角度看:
- 重復類似的操作:讀數據-運算-寫數據。
- 假設每行代碼執行事件都為 unit_time。(粗略估計)
- 代碼中執行的時間為:
T(n) = (2+3n)*unit_time。
-
結論:所有代碼的執行時間 T(n) 與每行代碼的執行次數成正比。
算法 2(嵌套 for 循環):
int cal(int n)
{
int sum = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i)
{
j = 1;
for (; j <= n; ++j)
{
sum = sum + i * j;
}
}
}
- 代碼中執行時間為:
T(n) = (3+3n+3n²)*unit_time=3(n²+n+1)*unit_time。 - 所有代碼的執行時間 T(n) 與每行代碼執行的次數成正比。
大 O 表示
T(n) = O(f(n))
-
上面算法 1 中的大 O 表示法為:
T(n) = O(2+3n)。 -
上面算法 2 中的大 O 表示法為:
T(n) = O(3(n²+n+1))。 -
大 O 表示法不是表示代碼真正的執行時間,而是表示代碼執行時間隨數據規模增長的變化趨勢。
- 即是時間復雜度。
當 n 很大時,公式中的低階、常量、系數三部分並不左右增長趨勢,所以都可以忽略。
只需要記錄一個最大量級就可以了,如果用大 O 表示法表示剛講的那兩段代碼的時間復雜度,可記為:
T(n) = O(n);T(n) = O(n²)。
時間復雜度分析
當了解了大 O 表示法后,就可以用來分析時間復雜度了。
三個實用的方法:
- 只關注循環執行次數最多的一段代碼。(多)
- 加法法則:總復雜度等於量級最大的那段代碼的復雜度。(大)
- 乘法法則:嵌套代碼的復雜度等於嵌套內外代碼復雜度的乘積。(嵌套:積)
關注執行最多的一段代碼
以上面算法 1 為例:
-
前面兩行代碼為常量級別,忽略。
-
3n中的系數也可忽略。 -
結論:時間復雜度為
O(n)
算法 2 的時間復雜度就是 O(n²)
加法規則
加法法則:總復雜度等於量級最大的那段代碼的復雜度。
- 公式:
T(n)=T1(n)+T2(n)=max(O(f(n)), O(g(n))) =O(max(f(n), g(n)))。
若上面算法 1 和算法 2 出現在同一個代碼段中是,其時間復雜度之和為 O(n)+O(n²)。
總的時間復雜度就是取最大量級: O(n²)。
乘法規則
乘法法則:嵌套代碼的復雜度等於嵌套內外代碼復雜度的乘積。
- 公式:
T1(n)=O(f(n)),T2(n)=O(g(n));那么T(n)=T1(n)T2(n)=O(f(n))O(g(n))=O(f(n)*g(n))。
例子:
- 時間復雜度:
T(n) = T1(n) * T2(n) = O(n*n) = O(n²)。
int func(int n)
{
int sum = 0;
int i = 1;
for (; i < n; ++i)
{
sum = sum + i;
}
return sum;
}
int cal(int n)
{
int ret = 0;
int i = 1;
for (; i < n; ++i)
{
ret = ret + func(i);
}
}
常見時間復雜度
常見時間復雜度量級如圖:

這些復雜度量級可分為:
-
多項式量級:
- 常量階:
O(1) - 對數階:
O(logn) - 線性階:
O(n) - 線性對數階:
O(nlogn) - k 次方階:
O(nk)(注意:這里的 k 為 k 次方)
- 常量階:
-
非多項式量級
- O(2n);(注意:這里的 n 為 n 次方)
O(n!)。- 說明:當數據規模 n 越來越大時,非多項式量級算法的執行時間會急劇增加,求解問題的執行時間會無限增長。所以,非多項式時間復雜度的算法其實是非常低效的算法。
常量階 O(1)
O(1) 只是常量級時間復雜度的一種表示方法,並不是指只執行了一行代碼。
大牛總結:(常量級記作 O(1))
- 只要代碼的執行時間不隨 n 的增大而增長,這樣代碼的時間復雜度我們都記作
O(1)。 - 或者說, 一般情況下,只要算法中不存在循環語句、遞歸語句,即使有成千上萬行的代碼,其時間復雜度也是
Ο(1)。
對數階 O(logn)、O(nlogn)
i=1;
while (i <= n)
{
i = i * 2;
}
時間復雜度分析過程:
-
多:第 4 行代碼執行次數最多。那就算出第四行執行的次數。
-

-
得 x = log2n 即時間復雜度為 O(log2n)。也就是
O(logn)。 -
不管底數為何值,都把這類對數階的時間復雜度記為
O(logn)。理由:- log3n = log32 * log2n。對應時間復雜度為:O(log3n) = O(C * log2n)。
- 按前面學的系數可忽略:O(log3n) = O(log2n)。
- 既然不同底數都可以轉化,那就直接使用
O(logn)來標記對數階。
而對於 O(nlogn) 就是一段時間復雜度為 O(logn) 的代碼段被執行了 n 次。
多參數階 O(m+n)、O(m*n)
分析代碼的時間復雜度由兩個以上數據的規模來決定。
以下以兩個數據規模決定為基礎。
int cal(int m, int n)
{
int sum_1 = 0;
int i = 1;
for (; i < m; ++i)
{
sum_1 = sum_1 + i;
}
int sum_2 = 0;
int j = 1;
for (; j < n; ++j)
{
sum_2 = sum_2 + j;
}
return sum_1 + sum_2;
}
- 其時間復雜度為:
O(m+n) - 對於加法規則(變了):T1(m) + T2(n) = O(f(m) + g(n))。
- 對於乘法規則(不變):T1(m)*T2(n) = O(f(m) * f(n))。
空間復雜度分析
空間復雜度。關聯到資源消耗。
- 空間復雜度全稱就是漸進空間復雜度,表示算法的存儲空間與數據規模之間的增長關系。
使用大 O 表示法,和時間復雜度一樣,只是分析的數據規模 n 由時間度量改為空間度量。
小結
復雜度也叫漸進復雜度,包括時間復雜度和空間復雜度,用來分析算法執行效率與數據規模之間的增長關系。
通常越高階復雜度的算法,執行效率越低。
常見的復雜度並不多,從低階到高階有:O(1)、O(logn)、O(n)、O(nlogn)、O(n2 )。

