複雜度分析

a瑶池發表於2024-03-20
複雜度分析是演算法中非常重要的一點,只有做了複雜度分析才能判斷自己目前選擇的方案是否是最適合
了,所以我們應該花一些時間在理解的基礎上去掌握如何分析一段程式碼複雜度
時間複雜度
概念:時間複雜度全稱為 漸進時間複雜度,表示演算法的執行時間與資料規模之間的增長關係。
幾種常見的時間複雜度有 O(1) O(n) O(logn) O(nlogn) O(n²) O(n*) *可以任意正數
複雜度的完整公式為T(n) = O(f(n)) 表示隨著執行次數n的增加,執行時間也成正比的增加,f函式就是
上面的這些種類
當你的程式中沒有迴圈,只會從頭到底執行一次, 時間複雜度就為O(1),你會說那我不止一行程式碼呀,真
實是O(4),沒關係,時間複雜度是一個隨著n增長的時間的粗略計算,這裡沒有迴圈,可以忽略 為 O(1)
當你的程式有一個n次的迴圈,那麼時間複雜度就是 O(n),下面例子真實執行時間為 O(n+2)頭尾兩行,但
隨著n的增長,2是可以忽略的,所以我們會歸為O(n),和上面忽略為O(1)是一個意思
當迴圈條件在迴圈中有乘法級別的運算時 如 i = 2*i 那麼迴圈次數為 log 2 n ,或者其他情況有包括以3
為n的對數等等,時間複雜度都忽略為O(logn),要知道這個時間複雜度明顯是小於 O(n) 的
其他的複雜度依次來類比就知道啦,O(n²) 是有巢狀迴圈的時間複雜度,O(nlogn)是logn複雜度迴圈的外
面還有一層n級別複雜度的迴圈
int cal(int n) {
int sum = 0;
int a = 1;
sum = a + n;
return sum;
}
int cal(int n){
int sum = 0;
for(int i = 0;i < n; i++){
sum = sum +i;
}
return sum;
}
int cal(int n){
int i = 1;
while(i <= n){
i = i *2;
}
}那麼如果程式碼中有好多種 複雜度級別的程式碼該如何判斷呢?
答案是以最高時間複雜度為最終結果。
空間複雜度
概念:漸進式空間複雜度,表示演算法的儲存空間和資料規模之間的增長關係。
常見的空間複雜度 有 O(1) O(n) O(n²)
如下程式碼,整體申請空間只有 長度為n的陣列a 和 整型 i ,i可以忽略,空間複雜度為 O(n)
其他以此類推
最好,最壞,平均情況時間複雜度
分析下這段程式碼,這個迴圈看起來時間複雜度像是O(n),元素可能出現在陣列中的任意位置,時間複雜度
可能是O(1),O(2).....O(n),其中O(1) 是最好情況時間複雜度 ,O(n)是最壞情況時間複雜度。那麼它的最
終複雜度應該為平均情況時間複雜度
除了上面分析的情況,還有一種情況是不在陣列中,(1+2+3+..+n+n)/(n+1) = n(n+3)/2(n+1),在大O標
記法中,可以省略掉係數,低階,常量,所以這個公式簡化後就是O(n)
更加嚴謹一些,還需要在這個計算公式中引入機率,即每種情況出現的次數,這裡假設 在不在陣列中的
機率各為1/2 ,0...n 每個的機率為1/n,則他們的實際機率為1/2n, 這個計算公式應該改為 1(1/2n)
+2(1/2n)+....n(1/2n)+n(1/2) = (3n+1)/4 ,這個值就是機率論中的加權平均值,也叫作期望值,所以平均
時間複雜度的全稱,也叫作加權平均時間複雜度或者期望時間複雜度,這段程式碼的加權平均時間複雜度
仍然是O(n)
注:只有同一塊程式碼在不同的情況下,時間複雜度有量級的差距,我們才會使用這三種時間複雜度
來區分
void pring(int n){
int i = 0 ;
int[] a = new int[n];
for(i;i < n; ++i){
a[i] = i*i;
}
}
int find(int[] array,int n,int x){
int i = 0;
int pos = -1;
for(;i<n;++i){
if(array[i] == x){
pos = i;
break;
}
}
return pos;
}均攤時間複雜度
假如陣列長度為n,上面的例子就是判斷當前插入個數,是否已經佔滿了陣列,如果陣列已滿,迴圈n
次,得到陣列的和,並清空陣列,如果沒滿,直接插入,分析一下,大多數情況 (n-1)時間複雜度為
O(1),最後一次時間複雜度為O(n),所以我們均攤一下,時間複雜度就是 O(1) ,這就叫做均攤時間複雜
度,均攤時間複雜度一般是最好時間複雜度
整理自《資料結構與演算法之美》
int[] array = new int[n];
int count = 0;
void insert(int val){
if(count == array.length ){
int sum = 0;
for(int i=0;i<array.length;++i){
sum = sum + array[i];
}
array[0] = sum;
count = 1;
}else{
array[count] = val;
++count;
}
}

相關文章