《程序員面試金典》+《算法導論》
由於最近可能會面臨一波面試,可是本身各類算法以及常見的問題的熟悉程度感受還不夠,可是由前幾回的代碼優化經驗來看,算法優化能夠說是代碼優化的重中之重,算法選取恰當每每會致使運行時間呈現多個數量級的降低,一直認爲算法纔是人類文化的結晶。所以此周就找了一本程序員面試的書籍配合算法導論閱讀。最後看了算法導論的排序與一些圖算法與面試書的考題簡介。java
瑣碎細節
由於面試並非單純知識能力的體現,更是一我的綜合素養的體現,面試官的印象會受到你言談舉止甚至穿衣搭配的影響,前文大概就是對這些瑣碎細節進行了一些交代,甚至對於合適的發郵件的時間,如何拒絕offer都進行了交代,這些仍是須要注意的,花了點時間隨便看了看。程序員
技術細節
基本上分了數組字符串處理,棧與隊列,樹與圖,位運算,遞歸與動態規劃進行講解,最後還講了一些語言方面的知識點(C,C++,JAVA),以及一些線程鎖的知識。下面順着來捋一下,順便補充上一些算法導論上看到的知識。面試
1 數組與字符串
面試書上包括鏈表,哈希表,普通數組,講了一個快行指針的技巧。算法
- 算法導論上,這部分主要講解的是字符串匹配算法,介紹了四種,最普通的,Rabin-Karp算法,利用有限自動機,最後是經典的kmp算法。應用上,此類算法能夠用於提升輸入法聯想的響應速度包括搜索DNA序列中的特定序列衡量標準有預處理時間與匹配時間。其中KMP算法最爲巧妙,將與預處理時間下降到O(m),並將實際的匹配時間控制到了O(n)。
- 哈希表,經過計算使得鏈表法散列實現的查找效率降到O(1+C),C爲負載係數,使得開放查找法O(1/(1-c)),算法導論中對其進行了證實,並對如何選擇合適的哈希函數提出了建議,好比除法散列法能夠選擇一個不接近2的整數次冪的素數做爲除數,乘法散列法能夠選擇(sqrt(5)-1)/2產生小數部分,另外還介紹了全域散列法,並給出了一個構造方法,惋惜我沒學過數論,並無看懂,也下定決心大四必定要補一些cs的基礎課。實現上能夠利用鏈表或者數組,前者更被推薦,負載係數能夠大於1,經過槽位拉鍊處理衝突,後者負載係數已更改小於1,經過線性探測,雙重散列(這裏還介紹了將第二次hash僅僅產生奇數而除數爲偶實現互素的小技巧)之類的方法處理衝突。
2 棧與隊列
面試書上講了java實現隊列與棧,並講述了幾道算法題目,比較有意思的是一道用一個數組實現三個棧的題目,要求三個棧是動態的即空間是動態的,想了一段時間,可是隻要注意合適的搬移與壓入的時候容許循環,即應當把整個數組當作先後相連的。數組
3 樹與圖
當初學數據結構的時候就以爲這部分知識點複雜瑣碎,幾個樹遍歷的非遞歸算法幾乎都寫不出來,可是遞歸又老是面臨爆棧的風險,藉此再複習了一下。 面試書中基本就仍是回顧了一些基本知識點,而後是題目,作了幾道,其中一道在一棵節點數巨大的二叉樹中查找子樹的題目頗有趣,算法思路是兩個樹徹底相同與先序遍歷與中序遍歷相同等價(注意條件爲樹必須除根外度都爲2,缺乏左右孩子應該置空)不然會出現下面的狀況,數據結構
斷定爲相同的樹,以後化爲了字符串匹配問題,可是這種方法必然會佔用大量的內存,由於要作遍歷儲存遍歷結果,有時候這是難以忍受的,另外一種方法是直接搜索較大的樹,一旦碰到有相同的根節點則對兩棵樹進行匹配。函數
算法導論上關於這部分就太多了,樹主要講解二叉搜索樹以及其插入刪除,並對其平均時間複雜度作出了證實。
更多的是關於圖的討論,圖的鏈表表示以及鄰接矩陣表示,圖的兩種遍歷,深度優先以及廣度優先。並各自對其應用作了簡單介紹。優化
- BFS搜索能夠用來創建每一個從一個節點開始到每一個節點的最短路徑,直覺上能夠這麼想,BFS是以開始節點爲圓心,一圈一圈的擴展搜索的,實現上,只要牢記其中隊列來保證訪問的層次應該就能寫出來.
- 關於深度優先遍歷,重點講了兩個時間,第一是個是第一次訪問到的時間v.d,另外一個是其下全部子孫訪問結束後的時間d.f,其後的許多算法都基於這個時間展開。
- 判別節點關係,只要[v.d,v.f]這個區間與其餘節點存在包含關係,則說明其中一個另外一個的子孫。
- 進行迴路檢測 3 . 進行拓撲排序(有向無環圖),按結束時間在鏈表頭進行插入。
- 查找強連通份量。這個算法感受十分巧妙,具體的證實花費了大量的篇章,思想上能夠這麼理解,首先將強連通份量塌縮成一個節點,不一樣的強聯通份量必然只有單向邊,稱塌縮後的圖爲份量圖,份量圖就必然是有向無環圖,以後定義塌縮點的.f與.d爲強聯通份量中的.f的最大值與.d的最小值,其中份量圖的邊與塌縮點的.f息息相關,就是邊指向的塌縮點的.f必定比邊發出的塌縮點.f要小,那麼先遍歷一遍圖,那麼.f最大的點必定在份量圖中拓撲排序的最後一個,按.f的倒序開始DFS遍歷圖的轉置,即G全部邊轉向,其必然不能跑到其餘強聯通份量,不然不可能爲一個獨立的強聯通份量,以此倒退,就找到了全部的強連通份量。 最後做者提出一個問題,假如按第一次訪問.f的增序直接訪問圖,是否是也是正確的,假如正確豈不是能夠省去求圖的轉置的時間(通常爲O(V+E)),其實不是這樣的,.f與份量圖的拓撲排序是一致的,可是.d不是,好比思考這樣的狀況,
從A開始遍歷,先走B,假如按上述算法,.f最小值爲B,從B遍歷則ABC爲強連通份量,顯然錯誤,這是由於聯通份量的.f最小值1與份量圖的邊的走向是沒有肯定關係的!!!!spa
總結
比較高深的圖算法以及排序,動態規劃尚未好好看,感受確實是沒有修過離散數學與圖論,看起來有點點吃力,能看完的話會再放到一篇讀書筆記裏面。
算法真的頗有意思,就是有點費腦子,尤爲是算法導論的證實比較晦澀,看了一週多,覺察到一個比較功利的見解,先看算法的應用,感興趣再看實現,而後思考大致的邏輯,若是以爲很對(好比BFS作最短路徑計算以及迴路檢測),就沒必要關心它的證實。,假如真的徹底不理解爲何這種算法是對的(好比利用DFS找尋強連通份量),就要仔細看證實,通常順着證實過程來就能理清其中的邏輯,還能加深理解。最後惟一不足的是時間有限沒來得及寫算法的實現,感受仍是要抽空寫一下的。