算法效率的度量方法
算法效率的度量方法:
算法采用的策略、方案
編譯產生的代碼質量
問題的輸入規模
機器執行指令的速度
由此可見,拋開計算機硬件,一個程序的運行時間依賴于算法的好壞和輸入規模。
例如1-100之間求和,兩種算法其實就是n和1的差距。
我們研究算法的復雜度,側重的是研究算法隨著輸入規模擴大增長量的一個抽象,而不是精確的定位需要執行多少次。
我們不關心語言、環境等,只關心它所實現的算法。
我們在分析一個算法的運行時間時,重要的是把基本操作的數量和輸入模式關聯起來
可以看出,n=1時,A算法不如B算法,隨著n的增長,A算法開始反超,總體來講算法A比B更優秀
算法時間復雜度
算法時間復雜度的定義:
(1)時間頻度: 一個算法執行所耗費的時間,從理論上是不能算出來的,必須上機運行測試才能知道。但我們不可能也沒有必要對每個算法都上機測試,只需知道哪個算法花費的時間多,哪個算法花費的時間少就可以了。并且一個算法花費的時間與算法中語句的執行次數成正比例,哪個算法中語句執行次數多,它花費時間就多。一個算法中的語句執行次數稱為語句頻度或時間頻度。記為T(n)。
(2)時間復雜度: 在剛才提到的時間頻度中,n稱為問題的規模,當n不斷變化時,時間頻度T(n)也會不斷變化。但有時我們想知道它變化時呈現什么規律。為此,我們引入時間復雜度概念。 一般情況下,算法中基本操作重復執行的次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近于無窮大時,T(n)/f(n)的極限值為不等于零的常數,則稱f(n)是T(n)的同數量級函數。記作T(n)=O(f(n)),稱O(f(n)) 為算法的漸進時間復雜度,簡稱時間復雜度。
一般情況下,隨著輸入規模n的增大,T(n)增長最慢的算法為最優算法
顯然,利用時間復雜度,可以算出我們的兩個求和算法的時間復雜度分別為O(1),O(n)。
推導方法:
用常數1取代運行中的所有加法函數
在修改后的運行次數函數中,只保留最高階項
如果最高階項存在且不是1,則去除與這個項相乘的常數
得到的最后結果就是O的階數
常數階:
這里舉一個例子
這里的時間復雜度并不是O(8),而是O(1),因為printf的次數并不隨著時間規模的增大而增大。
線性階
一般含有非嵌套循環涉及線性階,隨著n的增大,對應計算次數呈直線增長。例如
時間復雜度為O(n)。
平方階
對于嵌套的循環,例如:
時間復雜度為O(n)。
對數階
我們看下這個程序:
每次循環,i*2,離n更近一步,假設有x個2相乘后大于等于n,就會退出循環
于是由2^x=n得到x=Log2n,所以這個程序的時間復雜的為O(logn)。
上述代碼的時間復雜度為O(n^2);
常見的時間復雜度
例子 時間復雜度 類型 5201314 O(1) 常數階 3n+4 O(n) 線性階 3n^2+4n+5 O(n^2) 平方階 3log2n+4 O(logn) 對數階 2n+3nlog2n+14 O(nlogn) nlogn階 n^3 +2n^2+4n+6 O(n^3) 立方階 2^n O(2^n) 指數階常用的時間復雜度所耗費的時間從小到大依次是:
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)< O(n3)<O(2n)<O(n!)<O(n^n)所以說,算法分析中,我們查找一個有n個隨機數數組中的某個數字,最好的情況是第一個數字就是,那么時間復雜度就是O(1),但也有可能在這最后一個位置,就是O(n)。
平均運行時間是期望的運行時間
最壞運行時間是一種保證。在應用中,這是一種最重要的需求,通常除非特別指定,我們提到的運行時間都是指最壞情況的運行時間
算法的空間復雜度
首先我們要明白,我們在寫代碼時,完全可以用空間來換取時間。
舉個例子,判斷某一年是否為閏年,我們可以實現要給算法,每給一個年份,都會通過算法計算得到是否是閏年的結果。
另一種算法就是,建立一個數組,將所有年份按下標的數字對應,如果是閏年,則此數組元素對應的值為1,否則為0.
對比兩個算法,第一種算法很明顯節約空間,但是每一次查詢都需要進行運算,而第二種算法,雖然在內存中存了幾千個數組,但是每次查詢只需要一次索引即可。
這就是典型的空間換時間。
算法的空間復雜度通過計算算法所需的存儲空間實現,算法的空間復雜度的計算公式為:
S(n)=O(f(n)),其中,n為問題的規模,F(n)為語句關于n所存儲空間的函數。
通常,我們都是用"時間復雜度"來指運行時間的需求,是用"空間復雜的"值空間需求。
當直接要求我們求“復雜度”時,通常是指時間復雜度。
顯然,對時間復雜度的追求更屬于算法的潮流。
總結
- 上一篇: Spring注解大全(示例详解)
- 下一篇: 什么是堆和栈以及区别详解