程序員面試中,不少算法設計問題,都是歷年來各家企業的「炒現飯」,無論求職者之前對算法知識學習得是否紮實,理解得是否深刻,只要面試前買本《程序員面試筆試寶典》(備註:編者早前編寫的一本書,機械工業出版社出版),學習上一段時間,牢記於心,應付此類題目徹底沒有問題,但遺憾的是,不少世界級知名企業也深知這一點,若是純粹是出一些毫無技術含量的題目的話,對於考前「突擊手」而言,可能會佔盡便宜,但對於那些技術好的人而言是很是不公平的。因此,爲了把優秀的求職者與通常的求職者可以更好地區分開來,他們愈來愈傾向於出一些有技術含量的「新」題,這些題目以及答案,再也不是之前的陳穀子爛芝麻了,而是通過精心設計的好題。程序員
在程序員面試中,算法的地位就如同是GRE或托福考試在出國中的地位同樣,必須但不是最重要的,它只是衆多考覈方面中的一個而已,不必定就能決定求職者的生死。雖然如此,但並不是說明就不用去準備算法知識了,由於算法知識回答得好,必然會成爲面試的加分項,對於求職成功,百利而無一害。那麼如何應對此類題目呢?很顯然,編者不可能將此類題目都在《程序員面試筆試寶典》中一一解答,一來因爲內容衆多,篇幅有限,二來也不必,今年考過了,之後通常就不會再考了,否則仍是沒有區分度。編者覺得,靠死記硬背確定是行不通的,解答此類算法設計問題,須要求職者具備紮實的基本功以及良好的運用能力,編者沒法左右求職者的我的基本功以及運用能力,由於這些能力須要求職者「十年磨一劍」地苦學,但編者能夠提供一些比較好的答題方法和解題思路,以供求職者在面試時應對此類算法設計問題。「授之以魚不如授之以漁」,豈不是更好?面試
(1)概括法算法
此方法經過寫出問題的一些特定的例子,分析總結其中通常的規律。具體而言就是經過列舉少許的特殊狀況,通過分析,最後找出通常的關係。例如,某人有一對兔子飼養在圍牆中,若是它們每月生一對兔子,且新生的兔子在第二個月後也是每月生一對兔子,問一年後圍牆中共有多少對兔子。設計模式
使用概括法解答此題,首先想到的就是第一個月有多少對兔子,第一個月的時候,最初的一對兔子生下一對兔子,此時圍牆內共有兩對兔子。第二個月還是最初的一對兔子生下一對兔子,共有3對兔子。到第三個月除最初的兔子新生一對兔子外,第一個月生的兔子也開始生兔子,所以共有5對兔子。經過舉例,能夠看出,從第二個月開始,每個月兔子總數都是前兩個月兔子總數之和,Un+1=Un+Un-1,一年後,圍牆中的兔子總數爲377對。數組
此種方法比較抽象,也不可能對全部的狀況進行列舉,因此,得出的結論只是一種猜想,還須要進行證實。數據結構
(2)類似法學習
正如編者「年年歲歲花類似,歲歲年年仍單身」同樣,此方法考慮解決問題的算法是類似的。若是面試官提出的問題與求職者之前用某個算法解決過的問題類似,此時此刻就能夠舉一反三,嘗試改進原有算法來解決這個新問題。而一般狀況下,此種方法都會比較奏效。網站
例如,實現字符串的逆序打印,也許求職者歷來就沒遇到過此問題,但將字符串逆序確定在求職準備的過程當中是見過的。將字符串逆序的算法稍加處理,便可實現字符串的逆序打印。spa
(3)簡化法設計
此方法首先將問題簡單化,例如改變一下數據類型、空間大小等,而後嘗試着將簡化後的問題解決,一旦有了一個算法或是思路能夠解決這個被「閹割過」的問題,再將問題還原,嘗試着用此類方法解決原有問題。
例如,在海量日誌數據中提取出某日訪問xxx網站次數最多的那個IP。很顯然,因爲數據量巨大,直接進行排序不可行,但若是數據規模不大時,採用直接排序不失爲一種好的解決方法。那麼如何將問題規模縮小呢?因而想到了Hash法,Hash每每能夠縮小問題規模,而後在「閹割過」的數據裏面使用常規排序算法便可找出此問題的答案。
(4)遞歸法
爲了下降問題的複雜度,不少時候都會將問題逐層分解,最後歸結爲一些最簡單的問題,這就是遞歸。此種方法,首先要可以解決最基本的狀況,而後以此爲基礎,解決接下來的問題。
例如,在尋求全排列的時候,可能會感受無從下手,但仔細推敲,會發現後一種排列組合每每是在前一種排列組合的基礎上進行的從新排列,只要知道了前一種排列組合的各種組合狀況,只須要把最後一個元素插入到前面各類組合的排列裏面,就實現了目標:即先截去字符串s[1…n]中的最後一個字母,生成全部s[1…n-1]的全排列,而後再將最後一個字母插入到每個可插入的位置。
(5)分治法
任何一個能夠用計算機求解的問題所需的計算時間都與其規模有關。問題的規模越小,越容易直接求解,解題所需的計算時間也越少。而分治法正是充分考慮到這一點內容,將一個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。分治法通常包含如下三個步驟:1)將問題的實例劃分爲幾個較小的實例,最好具備相等的規模;2)對這些較小的實例求解,而最多見的方法通常是遞歸;3)若是有必要的話,合併這些較小問題的解,以獲得原始問題的解。
分治法是程序員面試常考的算法之一,通常適用於二分查找、大整數相乘、求最大子數組和、找出僞幣、金塊問題、矩陣乘法、殘缺棋盤、歸併排序、快速排序、距離最近的點對、導線與開關等。
(6)Hash法
不少面試筆試題目,都要求求職者給出的算法儘量高效。什麼樣的算法是高效的?通常而言,時間複雜度越低的算法越高效。而要想達到時間複雜度的高效,不少時候就必須在空間上有所犧牲,用空間來換時間。而用空間換時間最有效的方式就是Hash法、大數組、位圖法。固然,此類方法並不是包治百病,有時,面試官也會對空間大小進行限制,那麼,此時,求職者只能再去思考其餘的方法了。
其實,凡是涉及到大規模數據處理的算法設計中,Hash法就是最好的方法之一。
(7)輪詢法
每道面試筆試題,在設計時,每每會有一個載體,這個載體即是數據結構,例如數組、鏈表、二叉樹、圖等,當載體肯定後,可用的算法天然而然地就會暴露出來。可問題是不少時候並不肯定這個載體是什麼。當沒法肯定這個載體時,通常也就很難想到合適的方法了。
編者建議,此時,求職者能夠採用最原始的思考問題的方法——輪詢,在腦海中輪詢各類可能的數據結構與算法,常考的數據結構與算法一共就那麼一些,即便不徹底同樣,也是由此衍生出來的或是類似的,總有一款適合此題的。
表7.1 最常考的數據結構與算法知識點
數據結構 |
算法 |
概念 |
鏈表 |
廣度(深度)優先搜索 |
位操做 |
數組 |
遞歸 |
設計模式 |
二叉樹 |
二分查找 |
內存管理(堆、棧等) |
樹 |
排序(歸併排序、快速排序等) |
|
堆(大頂堆、小頂堆) |
樹的插入/刪除/查找/遍歷等 |
|
棧 |
圖論 |
|
隊列 |
Hash法 |
|
向量 |
分治法 |
|
哈希表 |
動態規劃 |
|
此種方法看似笨拙,其實實用,只要求職者對常見的數據結構與算法爛熟於心,一點都沒有問題。
爲了更好的理解這些方法,求職者能夠在平時的準備過程當中,應用此類方法去答題,作得多了,天然對各類方法也就熟能生巧了,面試的時候,再遇到此類問題,也就可以收放自如了。固然,千萬不要相信有着張無忌般的運氣,可以在一晚上之間練成乾坤大挪移這一絕世神功,稱霸武林,算法設計功力的練就靠得是平時一點一滴的付出和思惟的磨練。方法與技巧也許只是給面試打了一針「雞血」、喂一口大補丸,讓本身變得從容自信,真正的內力仍是一個長期的積累過程,不是速食產品可以比得了的。
明年就要就業了,這裏看到好的東西共享一下,但願對你們有所幫助,一樣也是給本身加油!