關鍵概念
要分析演算法的複雜度,通常需要分析迴圈的運行.
一,假如,某個迴圈體的複雜度是O(1),那麼這個迴圈的時間複雜度就是O(n).
for(int i = 0; i < n; i++){
//一些列複雜度為O(1)的步驟....
}
通常,如果某個迴圈結構以線性方式運行n次,並且迴圈體的時間複雜度都是O(1),那麼該迴圈的複雜度就是O(n).
即使,該迴圈跳過某些常數部分,只要跳過的部分是線性,那麼該迴圈體的時間複雜度仍就是O(n).
比如
int count = 1;
while(count < n){
count += 2;
//一些列複雜度為O(1)的步驟....
}
時間複雜度還是O(n)
二,如果迴圈體的複雜度是對數級的 如下
int count = 1;
while(count < n){
count *= 2;
//一些列複雜度為O(1)的步驟....
}
該迴圈是O(logn)的, 通常情況是2為底的 也就是O(log2n)
關鍵概念
迴圈的時間複雜度等於該迴圈體的複雜度乘以迴圈的次數...
三,嵌套迴圈複雜度分析...
for(int count1 = 0; count1 < n; count1++){
for(int??count2 = 0; count2 < n; count2++){
//一些列複雜度為O(1)的步驟....
}
}
在這種情況下應該 先計算內層迴圈的時間複雜度,然後用內層的複雜度乘以外層迴圈的次數.
最內層迴圈體的時間複雜度都是O(1)所以迴圈n次也就是O(n) 在乘以最外層for的n次.
所以得出結論 2層嵌套迴圈的時間複雜度 = O(1) * n*n = O(n2)
在分析嵌套迴圈複雜度的時候必將內層迴圈和外層虛幻都考慮進來
四,方法調用的複雜度分析
假如有如下代碼
for(int count = 0; count < n; count++){
printsum(n);
}
迴圈的階次等於迴圈體的階次乘以迴圈的次數.像這種情況迴圈體裡頭是一個方法的調用,那麼這個迴圈體的時間複雜度如何呢!
這個方法就是列印1~n的和.所以必須先計算方法體的的時間複雜度.
public void printsum(int count){
int sum = 1;
for(int i= 0; i sum += i;
}
System.out.print(sum);
}
記住,只有可啟動並執行語句才會增加時間複雜度,因此,上面方法裡的內容除了迴圈之外,其餘的可運行語句的複雜度都是O(1),
所以printsum的時間複雜度 = for的 O(n)+O(1) = 忽略常量 = O(n)
但是回想一下,我們讓程式列印1~n的和不需要用for迴圈 記得初中數學課上老師就給出了個公式 num = n*(n+1)/2
改
public void printsum(int count){
int sum = 1;
sum = count * (count+1)/2;
System.out.print(sum);
}
此時的 printsum 方法的階次就是O(1) -------->意味著最外層調用此方法的迴圈複雜度就從 O(n2) 改良為 O(n)
這是一個很大的提高.從這點就可以看出簡單演算法和高效演算法之間的差別了.
五如果一個方法體是由多個方法調用and多個迴圈組成的,那麼其複雜度又如何!
public void suixiangMethod(int n){
printsum(n);//1.1
for(int i= 0; i printsum(n);
}
for(int i= 0; i for(int k=0; k
System.out.print(i,k);
}
}
suixiangMethod 方法的時間複雜度需要計算方法體的各個成員的複雜度?
也就是1.1+1.2+1.3 = O(1)+O(n)+O(n2) ----> 忽略常數 和 非主要項 == O(n2)