演算法效能評估
人工智慧興起得時代,什麼神經網路、增強學習、深度學習等諸多牛掰的演算法讓人云裡霧裡,在學習各種各樣應用不同的演算法之前,不如緩一緩來了解一下如何來判斷一個演算法是好是壞。演算法好壞直接影響到程式執行的效率,曾經讀過一本關於中國象棋演算法設計的書籍,該書演算法設計的基本思路就是構建博弈樹進行深度遍歷搜素。理想的狀態就是搜尋到可以獲勝為止,但是象棋局面的複雜度搜尋起來足以讓你等到鬍子花白。所以作者採用了α-β搜尋剪枝的辦法來提高執行效率,這就使得博弈演算法變得比以往要好的多。
怎麼來評估演算法的好壞,主要兩個方面的判斷:時間複雜度&空間複雜度。不整些花裡胡哨牛掰哄哄的,直接上套路。
時間複雜度【O】的計算:(本質就是數程式執行次數)
- 用常數1取代執行時間中的所有加法常數。
- 在修改後的執行次數函式中,只保留最高階項。
- 如果最高階項存在且不是1,則改為1。
這樣得到的結果就是大O階。
假設計算機執行一次基礎程式碼需要執行一次運算,那麼下面的main函式中執行玩需要執行兩次運算。
加上for迴圈可以看出main函式中兩次迴圈後執行的運算次數為1+2*1+1 = 4次
運算次數的函式f(n) = 4,根據上面時間複雜度的計算規則第一條便知,時間複雜度是O(1),而不是O(4)。
時間複雜度的分類大致分為常數階、線性階、平方階、立方階、對數階等。比如某個函式的運算次數函式為f(n)=32 + 2n + 1,則時間複雜度為O(n3)。如下表:
常見的時間複雜度如下:
執行次數函式舉例 |
階 |
非正式術語 |
12 |
O(1) |
常數階 |
2n+3 |
O(n) |
線性階 |
3n²+2n+1 |
O(n²) |
平方階 |
5log2n+20 |
O(logn) |
對數階 |
2n+3nlog2n+19 |
O(nlogn) |
nlogn階 |
6n³+2n²+3n+4 |
O(n³) |
立方階 |
2n |
O(2n) |
指數階 |
時間消耗比較:
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
對於演算法的設計,資料量越大,對於時間複雜度的需求便越嚴格,否則時間的損耗都是不同數量級的差距。
空間複雜度【S】的計算:(就是計算演算法所需要的儲存空間)
公式:S(n) = O(f(n)),其中,n代表問題的規模,f(n)是語句關於n所佔儲存空間的函式。
空間複雜度不知道該說些什麼好,其實在編寫程式碼的時候,我們要有一種空間使用的概念,而不是說只知道自己在敲程式碼。尤其涉及到硬體開發,比如STM32,FPGA,嵌入式開發之類,它們不像PC機,由於濫用資源就會導致程式溢位空間不足。
很多時候我們會犧牲空間來換取時間,目的是提高程式的執行效率。假如可以以列舉式
羅列出來的結果,在空間允許的情況下我們就不用其他邏輯關係來計算,而是以查表得方式
直接獲得結果。