關於時間復雜度空間復雜度的理解
對於非科班出身的人來說,在學習算法的時候經常會遇到的問題就是關於對事件空間復雜度的 理解。
「大 O 表示法」的準確的數學描述方式非常枯燥,我在這裏就不貼出來湊字數了,其實大 O 表示法的意思挺簡單的,就是表示:隨著輸入的值變化,程序運行所需要的時間與輸入值的變化關系。
我們先看第一個代碼,這是一個函數,輸入一個數組,輸出這個數組裏元數的和。
int count(int a[], int n) { int result = 0; for (int i = 0; i < n; ++i) { result += a[i]; } return result; }
這裏的時間復雜度是O(n),即隨著n的增長,O(n)也隨之線性增長,我們用O(n)來表示這種線性時間復雜度
接下來我們來看第二行代碼
int binary_search(int A[], int key, int imin, int imax) { if (imax < imin) { return KEY_NOT_FOUND; } else { int imid = midpoint(imin, imax); if (A[imid] > key) return binary_search(A, key, imin, imid - 1); else if (A[imid] < key) return binary_search(A, key, imid + 1, imax); else return imid; } }
對於這個程序來說,如果它處理 N 個元素求和所花的時間是 T,那麽它處理 N 2 個元素的和所花的時間是多少呢?是 T 2 嗎?
如果頭腦算不清楚,我們可以拿實際的數字來實驗,二分查找每次(幾乎)可以去掉一半的候選數字。所以假如 N = 1024,那麽它最多要找多少次呢?答案是 10 次,因為 2^10 = 1024,每次去掉一半,10 次之後就只剩下唯一一個元素了。
好,這個時候,如果元素的個數翻一倍,變成 2048 個,那麽它最多要找多少次呢?相信大家都能算出來吧?答案是 11 次,因為 2 ^ 11 = 2048。
所以在這個例子中,輸入的元素個數雖然翻倍,但是程序運行所花的時間卻只增加了 1,我們把這種時間復雜度要叫「對數」時間復雜度,用 O(logN) 來表示。
除了剛剛講的「線性」時間復雜度和「對數」時間復雜度。我們還有以下這次常見的時間復度數。
「常數」時間復雜度,例如返回一個有序數組中的最小數,這個數因為始終在第一個位置,所以就不會受到數組大小的影響,無論數組多大,我們都可以在一個固定的時間返回結果。
「線性對數」時間復雜度,即 O(N*logN),這個復雜度比較常見,因為常見的高效的排序算法,都是這個時間復雜度,比如快速排序,堆排序,歸並排序等。
之前我很多次在網上看到說把1000萬次運算當做實際的1s來運算。我的計算機主頻是2.5GHZ,所以每秒可以執行25億次匯編指令,加入每次循環裏面的代碼可以產生250條匯編指令,才能夠得到1s1千萬次循環的結果,不是很確定,有機會可以yongxcode試一下
總結一下學習時間復雜度的知識對於我們的工作有什麽用:
-
對於不同的數據規模,能夠決策采用不同的解決方案。
-
了解什麽情況下用暴力解法就能夠解決問題,避免寫復雜的代碼。
-
在寫代碼之前,就能夠預估程序的運行時間,從而可以知道是否能夠滿足產品需求。
-
在程序出現性能瓶頸時,能夠有解決方案而不是抓瞎。
參考 https://www.cnblogs.com/mafeng/p/6831731.html
關於時間復雜度空間復雜度的理解