本文來自 酷殼 – CoolShell.cn 陳皓 撰寫的文章:html
算法面試多是微軟搞出來的面試方法,如今不少公司都在效仿,並且咱們的程序員也樂於解算法題,我我的覺得,這是應試教育的毒瘤!我在《再談「我是怎麼招程序員」》中比較保守地說過,「問難的算法題並無錯,錯的不少面試官只是在膚淺甚至錯誤地理解着面試算法題的目的。」,今天,我想增強一下這個觀點——我反對純算法題面試!(注意,我說的是純算法題)程序員
我再次引用我之前的一個觀點——面試
能解算法題並不意味着這我的就有能力就能在工做中解決問題,你能夠想一想,小學奧數題可能比這些題更難,但並不意味着那些奧數能手就能解決實際問題。算法
好了,讓咱們來看一個示例(這個示例是昨天在微博上的一個討論),這個題是——「找出無序數組中第2大的數」,幾乎全部的人都用了O(n)的算法,我相信對於咱們這些應試教育出來的人來講,不用排序用O(n)算法是很正常的事,連我都不禁自主地認爲O(n)算法是這個題的標準答案。咱們太習慣於標準答案了,這是我國教育最悲哀的地方。(廣義的洗腦就是讓你的意識依賴於某個標準答案,而後經過給你標準答案讓你不會思考而控制你)shell
試想,若是咱們在實際工做中獲得這樣一個題 咱們會怎麼作?我必定會分析這個需求,由於我懼怕需求將來會改變,今天你叫我找一個第2大的數,明天你找我找一個第4大的數,後天叫我找一個第100大的 數,我不搞死了。需求變化是很正常的事。分析完這個需求後,我會很天然地去寫找第K大數的算法——難度一會兒就增大了。編程
不少人會覺得找第K大的需求是一種「過早擴展」的思路,不是這樣的,我相信咱們在實際編碼中寫過太多這樣的程序了,你必定不會設計出這樣的函數接口 —— Find2ndMaxNum(int* array, int len),就好像你不會設計出 DestroyBaghdad(); 這樣的接口,而是設計一個DestoryCity( City& ); 的接口,而把Baghdad當成參數傳進去!因此,你應該是聲明一個叫FindKthMaxNum(int* array, int len, int kth),把2當成參數傳進去。這是最基本的編程方法,用數學的話來講,叫代數!最簡單的需求分析方法就是把需求翻譯成函數名,而後看看是這個接口不是很二?!數組
(注:不要糾結於FindMaxNum()或FindMinNum(),由於這兩個函數名的業務意義很清楚了,不像Find2ndMaxNum()那麼二)數據結構
性能之類的東西曆來都是非功能性需求,對於算法題,咱們太喜歡研究算法題的空間和時間複雜度了。咱們但願作到空間和時間雙豐收,這是算法學術界的風格。因此,習慣於標準答案的咱們已經失去思考的能力,只會機械地思考算法以內的性能,而忽略了算法以外的性能。函數
若是題目是——「從無序數組中找到第K個最大的數」,那麼,咱們必定會去思考用O(n)的線性算法找出第K個數。事實上,也有線性算法——STL中 能夠用nth_element求得相似的第n大的數,其利用快速排序的思想,從數組S中隨機找出一個元素X,把數組分爲兩部分Sa和Sb。Sa中的元素大 於等於X,Sb中元素小於X。這時有兩種狀況:1)Sa中元素的個數小於k,則Sb中的第k-|Sa|個元素即爲第k大數;2) Sa中元素的個數大於等於k,則返回Sa中的第k大數。時間複雜度近似爲O(n)。性能
搞學術的nuts們到了這一步必定會歡呼勝利!可是他們哪裏能想獲得性能的需求分析也是來源自業務的!
咱們一說性能,基本上是我的都會問,請求量有多大?若是咱們的FindKthMaxNum()的請求量是m次,那麼你的這個每次都要O(n)複雜度的算法獲得的效果就是O(n*m),這一點,是書呆子式的學院派人永遠想不到的。由於應試教育讓咱們不會從實際思考了。
根據上面的需求分析,有軟件工程經驗的人的解法一般會這樣:
1)把數組排序,從大到小。
2)因而你要第k大的數,就直接訪問 array[k]。
排序只須要一次,O(n*log(n)),而後,接下來的m次對FindKthMaxNum()的調用全是O(1)的,總體複雜度反而成了線性的。
其實,上述的還不是工程式的最好的解法,由於,在業務中,那數組中的數據可能會是會變化的,因此,若是是用數組排序的話,有數據的改動會讓我從新排序,這個太耗性能了,若是實際狀況中會有不少的插入或刪除操做,那麼能夠考慮使用B+樹。
工程式的解法有如下特色:
1)很方便擴展,由於數據排好序了,你還能夠方便地支持各類需求,如從第k1大到k2大的數據(那些學院派寫出來的代碼在拿到這個需求時又開始撓頭苦想了)
2)規整的數據會簡化總體的算法複雜度,從而總體性能會更好。(順序的處理很容易進行各類處理)
3)代碼變得清晰,易懂,易維護!(學院派的和STL同樣的近似O(n)複雜度的算法沒人敢動)
你必定會和我爭論,
看過這上面的分析,我相信你明白我爲何反對純算法面試題了。緣由就是純算法的面試題根本不能反應一個程序的綜合素質!
那麼,在面試中,咱們應該要考量程序員的那些綜合素質呢?我覺得有下面這些東西:
另外,咱們知道,對於軟件開發來講,在工程上,難是的下面是這些挑戰:
因此,對於編程能力上,咱們應該主要考量程序員的以下能力:
因此,這段時間,我愈來愈傾向於問應聘者一些有業務意義的題,並且應增長或更改需求來看程序員的重構代碼的能力,寫完程序後,讓應聘者設計測試案例。
好比:解析加減乘除表達式,字符串轉數字,洗牌程序,口令生成器,經過ip地址找地點,英漢詞典雙向檢索……
總之,我反對純算法面試題!