最近忽然萌生了一個想法,好好系統的學習一下算法與數據結構而後產生一系列的文章來回顧與總結學到的東西,這部分我想從最簡單的部分一一介紹總結,包括一些很基礎的內容
面試
之前在學校的時候就知道 程序 = 算法 + 數據結構,程序的做用是用來處理與解決現實問題,而在描述與解決現實問題時不可避免的會涉及到數據,如何將這些數據有效的組織起來並利用必定的方法來運算與處理應該算是程序的核心問題。算法
固然若是僅僅將編程做爲謀生的手段,確實不用太關心這部分,現實中不少語言和庫都封裝了這些東西,須要的時候直接用便可,不懂算法與數據結構並不會對編程產生什麼影響,在實際工做中可能並無機會本身實現一個鏈表、隊列等等。可是若是真正熱愛這一行,但願能更上一層樓的,算法與數據結構一定是繞不開的一環。編程
學習數據結構並非爲了要在工做中本身實現它,而是:數據結構
當時在學校學習的時候我是被各類系統程序以及各類漂亮的Web程序給吸引了,認爲算法這種東西永遠都在處理平時根本碰不上的問題,有時間浪費在這些虛無縹緲的東西上還不如學學怎麼作一個應用,寫一個網站出來。那個時候基本放棄了對這方面的學習。後來在工做中常常出現網上對你所面臨的問題沒有明確的結局方案,須要在現有的方案上作修改,這個時候就一籌莫展了。使用了某種算法解決了問題,可是效率不高,遇到大規模訪問時容易出錯崩潰,這個時候仍是沒轍。還有就是在網上看別人的開源代碼時須要花額外的精力來研究老外的某個寫法,其實若是懂點算法的知識,可能並不須要這些額外的時間開銷。函數
因爲有了這些精力,我想在新年開始的這段時間裏研究一下數據結構與算法的相關內容,提高一下本身的基本功。性能
有了前面說的一些經歷,下面就進入正題了:算法的時間複雜度與空間複雜度;
時間複雜度與空間複雜度是評價一個算法好話的一個經常使用標準。時間複雜度是以程序代碼中基本語句執行次數做爲衡量標準。換句話說時間複雜度是用這個算法須要執行代碼量來評價的。學習
假設一個問題的規模爲n,常見的好比說有n個數據須要進行處理,若是算法是相似這樣的:優化
for(int i = 0; i < n; i++) { //do some thing setup1(); for(int j = 0; j < n; j++) { //do something setup2(); } }
假設setup1和setup2 函數執行了j、k次運算 那麼咱們來計算一下這個算法總共執行了多少次:網站
首先在內層循環中循環了n次,那麼setup2函數執行了nci,這個時候有 k * n
, 外層循環也是執行了n次,因此這個算法總共執行了 n * (j + n * k) = n^2 + n(k + j)
, 這樣獲得事件複雜度爲 T(n) = n^2 + n(k + j)
因爲k j都是常數,因此計算這個時間複雜度又能夠寫做 T(n) = n^2 + nt
, 對於這個表達式取自高次冪 獲得這個算法的時間複雜度爲 T(n) = n^2
code
從上面的計算來看,計算事件複雜度就是計算它須要執行基本代碼執行多少次,而後將獲得的表達式取最高次冪並去掉係數。
常見的時間複雜度有O(1)、O(logn)、O(n)、O(nlogn)、O(n^2)、O(n^k)、O(n!)、O(2^n)
從效率上看,它們是依次下降的。通常來講算法最多達到O(n^2), 若是比O(n^2)高,這個時候就須要好好考慮一下優化算法了。
通常常見的算法時間複雜度以下:
空間複雜度是指算法佔用內存空間的值,須要注意的是,這個內存佔用主要是在算法內部動態分配了內存,算法函數中的臨時變量儲存在棧空間,算法執行完成後會回收,通常不考慮局部變量佔用的內存。同時靜態變量,全局變量都不考慮進來
在算法中值考慮在函數中分配的內存以及遞歸調用時棧空間的佔用內存。
計算算法的空間複雜度並不複雜,所以這裏就不給例子了。算法的空間複雜度應該控制在O(1),也就是儘可能不要在算法內部分配內存,少用遞歸。