總結自:資料結構與演算法之美
目錄空間複雜度分析
最好、最壞時間複雜度
平均時間複雜度
事後統計法有非常大的侷限性。
1.測試結果非常依賴測試環境
硬體的不同對測試結果有很大的影響。
2.測試結果受資料規模的影響很大
排序演算法依賴待排資料的有序度。此外,測試資料規模太小,測試結果可能無法真實地反映演算法的效能。
【示例】求1,2,3……n的累加和。
int cal(int n)
return sum;
}
解題思路:假設每行**執行時間都一樣,為unit_time
第4 5行都執行了 n 遍,所以需要 2n*unit_time的執行時間。
所以複雜度為 o(n)。
結論:
儘管不知道unit_time的具體值,但通過推到,可以得到乙個規律:所有**的執行時間t(n)與每行**的執行次數f(n)成正比
總結為乙個公式:
具體解釋:
t(n)表示**執行的時間;
n表示資料規模的大小
f(n)表示每行**執行的次數總和
所以,第乙個例子中t(n) = o(2n+2)。而時間複雜度實際上表示**執行時間隨資料規模增長的變化趨勢。這裡其實引用的是極限的思想,當n趨近於無限大時,常量、低階、係數對資料的影響無限趨近於0,所以省略這部分。得到最終的時間複雜度。
1.只關注迴圈執行次數最多的一段**
剛剛已經說了我們通常會忽略掉公式中的常量、低階、係數,只需要記錄乙個最大階的量級就可以了。所以我們在分析乙個演算法、一段**的時間複雜度的時候,也只關注迴圈執行次數最多的那一段**就可以了
2.加法法則:總複雜度等於量級最大的那段**的複雜度
【示例】
int cal(int n)
int sum_2 = 0;
int q = 1;
for (; q < n; ++q)
int sum_3 = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i)
}return sum_1 + sum_2 + sum_3;
}
思路分析**分為3部分,分別是求 sum_1, sum_2, sum_3。分別分析三段的時間複雜度。再取乙個量級最大的作為整個**的時間複雜度。
那麼整段**的時間複雜度就是 o(n^2)
3.乘法法則:巢狀**的複雜度等於巢狀內外**複雜度的乘積
【示例】
int cal(int n)
} int f(int n)
return sum;
}
思路分析如果 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)).
回到**上,f()方法的時間複雜度為 o(n);4~6行**的時間複雜度為 o(n)。那麼整個cal()的時間複雜度為 o(n^2)
基本概念:
粗略的將複雜度量級分為多項式量級和非多項式量級。非多項式量級只有兩個:o(2^n)和o(n!)
1.o(1)
一般情況下,只要演算法中不存在迴圈語句、遞迴語句,即使有成千上萬行的**,其時間複雜度也是ο(1)。
【示例】
int i = 8;
int j = 6;
int sum = i + j;
2.o(logn)、o(nlogn)
【示例】
i=1;
while (i <= n)
思路分析變數 i 的值從 1 開始取,每迴圈一次就乘以 2。當大於 n 時,迴圈結束。
變數 i 的取值就是乙個等比數列
如圖,通過2x=n求解 x。得出x = log2
n實際上,不管是以 2 為底、以 3 為底,還是以 10 為底,我們可以把所有對數階的時間複雜度都記為 o(logn)。
比如,log3
n = log3
2 * log2
n 而 log3
2 是乙個常量,因此以幾為底無所謂。
理解了 o(logn),那麼 o(nlogn) 實際上就是把複雜度為 o(logn) 的**執行了 n 遍。
3.o(m+n)、o(m*n)
【示例】
int cal(int m, int n)
int sum_2 = 0;
int j = 1;
for (; j < n; ++j)
return sum_1 + sum_2;
}
從**中可以看出,m 和 n 是表示兩個資料規模。我們無法事先評估 m 和 n 誰的量級大,所以我們在表示複雜度的時候,就不能簡單地利用加法法則,省略掉其中乙個。所以,上面**的時間複雜度就是 o(m+n)。
根據乘法法則,t1(m)*t2(n) = o(f(m) * f(n))。
空間複雜度全稱就是漸進空間複雜度(asymptotic space complexity),表示演算法的儲存空間與資料規模之間的增長關係。
【示例】
void print(int n)
}
思路分析第 3 行申請了乙個大小為 n 的 int 型別陣列,除此之外,剩下的**都沒有占用更多的空間,所以整段**的空間複雜度就是 o(n)。
【示例】
// n表示陣列array的長度
int find(int array, int n, int x)
} return pos;
}
最好情況:第乙個元素是要查詢的變數 x。時間複雜度 o(1)
最壞情況:最後乙個元素是要查詢的變數 x,或者陣列中沒有變數 x。時間複雜度 o(n)。
最好時間複雜度:在最理想的情況下,執行這段**的時間複雜度。
最壞時間複雜度:在最糟糕的情況下,執行這段**的時間複雜度。
繼續分析上個示例
陣列中存在或者不存在 x 的概率都為 1/2。
陣列中查詢任意位置出現 x 的概率為 1/n。
根據乘法法則,查詢資料出現在 0~n-1任意位置的概率為 1/(2n)。平均時間複雜度計算:
這個值就是概率論中的加權平均值,也叫作期望值,所以平均時間複雜度的全稱應該叫加權平均時間複雜度或者期望時間複雜度。
複雜度分析 時間複雜度 空間複雜度
執行效率是演算法的乙個重要的考量指標,演算法的執行效率用時間 空間複雜度來衡量。今天我們來學習一下複雜度的分析。通常我們可以通過執行程式來獲得演算法的真正的執行時間,這種方法我們可以稱為事後統計法,但這種方法得到的是具體的資料,測試結果很依賴測試環境,而且受資料規模影像最大。因此,我們需要乙個不需要...
複雜度分析 時間複雜度分析和空間複雜度分析
其實,只要講到資料結構與演算法,就一定離不開時間 空間複雜度分析。而且我個人認為,複雜度分析是整個演算法學習的精髓,只要掌握了它,資料結構和演算法的內容基本上就掌握了一半。1.時間複雜度分析 對於剛才羅列的複雜度量級,我們可以粗略地分為兩類,多項式量級和非多項式量級。其中,非多項式量級只有兩個 o ...
複雜度分析(上)時間複雜度 空間複雜度
為了肉眼 實時 快速地來分析出 的複雜度,我們需要乙個不用具體的測試資料來測試,就可以粗略地估計演算法的執行效率的方法。時間複雜度 空間複雜度 表示演算法的執行時間與資料規模之間的增長關係。每行 對應的 cpu 執行的個數 執行的時間都不一樣,但是,我們這裡只是粗略估計,所以可以假設每行 執行的時間...