做爲開發人員,咱們都但願在完成功能的基礎上讓代碼運行的更快、更省空間,那如何衡量編寫的代碼是否更有效率,這就須要咱們學會如何分析代碼時間複雜度和空間複雜度.算法
執行時間和佔用空間是代碼性能的2個評判標準,咱們分別用時間複雜度和空間複雜度去描述這2個標準,兩者統稱複雜度,複雜度描述的是算法執行時間(或佔用空間)隨數據規模的增加關係.性能
有人可能想問我代碼運行一下不就知道他執行多長時間了嗎,爲何還須要複雜度分析,確實你可以經過這種方法評估出代碼的執行效率,可是這樣會有一些侷限性.測試
1.測試結果太過於依賴測試環境
同一段代碼在不一樣處理器的機器上運行結果是顯然不同的,這時就不知道應該參考哪一個測試結果.
2.測試結果受到數據規模的影響很大
兩段不一樣的代碼在數據量比較小的時候可能相差甚微,沒法真實反映代碼的性能問題.code
因此咱們須要一個不依賴測試環境同時也不須要有具體的測試數據就能粗略的估計代碼的執行效率的方法,也就是複雜度分析.遞歸
大O複雜度表示法
先看一段代碼,求1,2,3...n的累加和開發
int calc(int n) { int sum = 0; //第一行 for(int i = 1; i <=n; i++) { sum = sum + i; } return sum; }
咱們來評估一下這段代碼的執行時間,假設每行執行的時間同樣,爲row_time.第1行須要一個row_time的執行時間,第2,3行分別執行了n次,因此須要2n*row_time的執行時間,因此這段代碼加起來總共的執行時間爲(2n+1)*row_time,雖然咱們並不知道row_time的具體時間,但咱們發現代碼的總執行時間T(n)與代碼的執行次數n成正比.咱們能夠用公式來表示效率
T(n) = O(f(n))
T(n)表明代碼的總執行時間,f(n)表明代碼的執行次數,O表明T(n)與f(n)成正比.因此上面的例子中,T(n) = O(2n+1),咱們能夠看出大O時間複雜度表示代碼執行時間隨數據規模的變化趨勢,咱們簡稱爲時間複雜度.基礎
當n很大時,公式中的常量,係數均可以忽略不計,並不會對變化趨勢有太大影響,咱們只需記下一個最大量級便可,那麼剛剛的例子最後就能夠記爲T(n) = O(n)循環
那之後的代碼如何去分析其時間複雜度呢,咱們有如下法則:
1.看代碼執行次數最多的一段,好比循環
2.多段代碼取最大量級,好比單循環和多重循環,應取多重循環的複雜度
3.嵌套代碼複雜度等於嵌套內外代碼複雜度的乘積,好比遞歸和多重循環等方法
平時咱們有一些經常使用的複雜度級別,好比O(1) (常數階)、O(logn) (對數階)、O(n) (線性階)、O(nlogn) (線性對數階)、O(n²) (平方階)
瞭解了時間複雜度,那麼空間複雜度也不難理解了,時間複雜度表示的是算法執行時間隨數據規模增加的變化關係,那空間複雜度則表示的是算法存儲空間隨數據規模增加的變化關係.
複雜度用來分析算法執行效率與數據規模增加的變化關係,越高階複雜度的的算法執行效率也就越低,上面列舉的複雜度級別從低到高分別爲O(1)、O(logn)、O(n)、O(nlogn)、O(n²).