一. 定義:
在進行演算法分析時,語句總的執行次數T(n) 是關於問題規模n的函式, 進而分析T(n) 隨 n 的變化情況並確認T(n) 的數量級。 演算法的時間複雜度,也是演算法的時間度量,記作:T(n) = O(f(n)). 它表示隨問題規模的增大,演算法執行時間的增長率和f(n) 的增長率相同 稱作演算法的漸近時間複雜度,簡稱時間複雜度. 其中f(n)是問題規模n 的 的某個函式
二. 推導大O階方法
- 用常數1 取代執行時間中的所有加法常數
- 在修改後的執行次數函式中, 只保留最高階項
- 如果最高階項相乘一個常數且不是1, 則去掉這個常數
1. 常數階時間複雜度 : O(1)
- 以下程式片段的時間複雜度函式 :f(n) = 1+1+1 = 3
- 根據推導大O階方法第一條: 用1 代替常數項
- 所以,時間複雜度為O(f(n)) = O(1); 稱為常數階
int sum = 0, n= 100; //執行一次
int sum = 0, n= 100; //執行一次
int sum = 0, n= 100; //執行一次
複製程式碼
2. 線性階時間複雜度: O(n)
- 以下程式片段的時間複雜度函式 :f(n) = n
- 根據推導大O階方法第二條: 只保留最高階項
- 所以,時間複雜度為O(f(n)) = O(n); 稱為線性階
for (int i = 0; i < n ; i++) {
System.out.println("i = "+i); // 執行n次
}
複製程式碼
3. 對數階時間複雜度 :O(logn)
- 以下程式片段的時間複雜度函式 :f(n) = log(2)n
- 所以,時間複雜度為O(f(n)) = O(logn); 稱為對數階
int count = 1;
while(count < n ){
// 每執行一次,count 乘 2
// 設x次後, count 大於 n ; 終止程式
// 所以函式; 2^x = n --> x = log(2)n
count = count*2; // 這裡執行 log(2)n 次
}
複製程式碼
4. 平方階時間複雜度:O(n^2)
example 1:
- 以下程式片段為雙重迴圈,所以執行次數為每個迴圈次數的乘積;時間複雜度函式 :f(n) = n^2
- 根據推導大O階方法第二條: 只保留最高階項
- 所以,時間複雜度為O(f(n)) = O(n^2),稱為平方階
for (int i = 0; i < n; i++) {
for (int j = 0; j < n ; j++) {
System.out.println("i = "+i+" j="+j); //執行n*n次
}
}
複製程式碼
example 2:
- 以下程式片段時間複雜度函式 :f(n) = n^2/2+n/2
- 根據推導大O階方法第二條: 只保留最高階項 :f(n) = n^2/2
- 根據推導大O階方法第三條: 如果最高階項相乘一個常數且不是1, 則去掉這個常數:f(n) = n^2
- 所以, 時間複雜度為O(f(n)) = O(n^2),稱為平方階
for (int i = 0; i < n; i++) {
for (int j = i; j < n ; j++) {
// 注意; 內層的j = i,
//所以,每次i 增加 1, 內層迴圈就減少一次
// 則,
// 當i=0; 時,內層迴圈執行 n次
// 當i=1時, 內層迴圈執行 n-1 次
//....
//當i=n-1, 內層迴圈執行 1 次
// 所以,總執行次數相加為: n+(n-1)+(n-2)+...+1 = n(n+1)/2 【高斯求和】
System.out.println("i = "+i+" j="+j);
}
}
複製程式碼
三、常見的時間複雜度
執行次數函式 | 階 | 非正式術語 |
---|---|---|
12 | O(1) | 常數階 |
2n+3 | O(n) | 線性階 |
3n^2+2n+1 | O(1) | 平方階 |
5log(2)n+20 | O(logn) | 對數階 |
2n+3nlog(2)n+19 | O(nlogn) | nlogn階 |
6n^3+2n^2+3n+4 | O(n^3) | 立方階 |
2^n | O(2^n) | 指數階 |