許多知名公司會對面試者進行演算法的測驗,受試者通常被提示可以使用白板,然而,這方式也引發了一些爭議,最著名的案例之一,就是Homebrew的作者Max Howell,在2015年,他於Twitter發出的Google面試經驗,聲稱其無法在白板上反轉二元樹而被刷下來。

就我來看,白板上的演算法是個遊戲規則,開發者也可以運用這規則來進行刻意練習。

白板手寫演算的爭議

開發者如果有志於一些(國際)知名公司,多少都會搜尋、查看一些面試教戰手則,從早期像是在考腦筋急轉彎的試題,到現在幾乎必然提到的,面試過程中往往會有一關是測驗演算法,而且沒有電腦可以使用,必須得在白板上撰寫程式。

然而,在白板上手寫程式碼真的有意義嗎?而且演算法相關的題目太多了,若沒有刻意練習或記憶,有可能在面試時寫出或闡述細節嗎?

聲稱被白板演算法刷下來的人,也包括工作多年、也有所成就的知名開發者,看法也是正反兩方都有。

以Max Howell的例子來說,有人認為他是去應徵iOS職缺,卻不問iOS領域專業而問演算法,實在有失公平,就連Google自家工程師都為此表示意外,而有人認為反轉二元樹是個基本題目,就算是Homebrew作者,也不應該寫不出來(Max Howell後來補充,他其實已經寫出來,可能是對方不滿意)。

不過近來,越來越多開發者反對這種面試過程,像是Rails作者David Heinemeier Hansson今年二月才剛發布的一則Twitter訊息,他自嘲說,要他在白板上寫泡沫排序一定會失敗,因為他都在網路上找程式碼。

DHH只是個開端,在〈Programmers are confessing their coding sins to protest a broken job interview process〉(https://goo.gl/H6z641)上,就列出了許多接力的自嘲者,其中還包括了在Google的Lead,有著三十年工作經驗的Tim Dierks,也自嘲他得搜尋一下,才拿得到Python的字串長度。

在〈Why I Don't Talk to Google Recruiters〉(https://goo.gl/rto8Bx)也談到自己不愉快的面試經驗,因為在收到面試邀請時,並沒有任何訊息顯示他們要找的是演算法專家,為什麼現場面試時,要他在白板上當場發明出演算法呢?

為演算法刻意練習

對我來說,面試經驗其實寥寥可數,幸運的是,沒有一次是在白板上接受演算法的試煉,不然,也許也是當場被刷下來,不過,這並不是說我平常沒在練習演算法,事實上,從打算進入程式設計領域的一開始,我就持續刻意收集演算法的相關題目,因為在還沒遇過任何待解的實務問題之前,演算法相關書籍中的題目,是刻意練習的好對象。

然而,我並不是個記憶力很好的人,容易遺忘演算的相關細節,因此做過的題目,就整理在〈常見程式演算〉(https://goo.gl/Uu1bbz)之中,早期這些題目多半都使用C或Java實作,說老實話,通常是看了題目直接看解答,僅偏重於解法的觀摩、程式碼的臨摹,很多題目並沒有特別去做自行思考。

隨著在程式設計領域的經驗增加,每學習一門語言,我總會回頭刻意練習那些演算法,一方面複習,二方面用以測試對新語言的熟練程度,而且,在這個階段,我偏重於語言間的翻譯。直到後來,接觸了函數式典範,用此典範思考演算法的思路,多半與命令式不相同,而且,通常找不到既有的程式碼可以參考,如果沒有清楚思考題目及演算的本質,很難將程式實現,為此,我刻意使用Haskell來進行練習,第一次享受到自行思考演算流程的樂趣(與自虐)。

實際上,當刻意在這些題目上做練習時,那段期間在演算思考上就會熟練而流暢,然而,假以時日焦點轉移到其他主題上,那些細節就又會遺忘。

而這也是一些開發者對白板面試的疑惑,為了符合遊戲規則,勢必得花費大量時間來準備演算法的練習,面試官怎麼區分真正的理解與死背?又或者面試官出了沒準備過的題目呢?當場發明演算法?

如果開發者曾真正試著自行思考出(最佳的)演算法,會知道這往往需要時間!

為面試刻意練習

這個世界有需求就會有供給,實際上面試時會問演算法,也不是一天兩天之事,也就因此會有一些人收集相關題目,編著成面試教戰手冊,像是我手邊就有本早期的《程式之美-微軟技術面試心得》,根據裏頭〈面試雜談〉中的Q&A看來,那時,似乎還不流行在白板上做這種事。

就現今而言,為了面試而想要刻意練習演算的話,開發者大概會想到LeetCode(https://leetcode.com),上面收集了許多大公司曾出過的演算題目,LeetCode大約創立於2011年前後,是演算法面試盛行下的產物,早期某些面試經驗談,都會說面試某公司前,上面的題目最好都刷過幾遍以上,比較會有把握!

LeetCode網站的創始者也出了本《Cracking the Coding Interview》,為了避免面試者刻意背誦題目,據說有些公司明文規定,不可以問這本書上的題目;相對地,也許是因為開發者大多知道要刷LeetCode了,題目也就越來越多元,而LeetCode的題目也從一開始的150題,增加到現在的500多題,想多刷幾遍題目,單就時間成本,都是個難事了。

就我來看,是否採用白板上的演算法進行面試,視公司文化、需求、體制等問題而定,事實上,有些公司還會直接標榜了他們有白板面試,而引以為傲,面試必然是要做準備的,這包括了去認識該公司面試時的遊戲規則,如果明擺著就是要過這關,那就要看看自己,想不想符合遊戲規則,而去做刻意練習了。

這甚至包括了真正在白板上練習,如果開發者曾經試過,應該會知道,想要清楚地在白板上寫好程式,並不容易。

如果覺得這遊戲規則不適合自己,那在一開始,也許就像〈Why I Don't Talk to Google Recruiters〉中寫的,把自己的遊戲規則也加上去,如果雙方遊戲規則無法契合,那就不要浪費雙方時間了。

選個對象刻意練習

不過,如果自己並非演算法專家,平常也不容易接觸到演算法,透過一些演算法題目、面試手冊或者網站,進行刻意的練習倒也不錯,除了演算法本身之外,也可以結合自身目的,像是刻意符合語言的典範、刻意使用某個程式庫來解題,演算上的快速或節省空間,不一定要是唯一考量。

舉例來說,我最近去LeetCode上玩了一下,目前來說,都是自行解題而不看解答,而解題時,可以用到標準API的就用,並偏好將函式寫得簡短、清楚易懂而不是最快速,甚至是用到一些典範,像是在LeetCode上也看到,有人偏好用Java 8的Stream API,以流暢風格來解題。

或者,像是TDD(Test-Driven Development)傳教士Joey Chen,最近在其部落格In 91(https://goo.gl/L8yqT2),分享運用TDD來刷LeetCode的方式也很不錯。

針對偏重現實場景的刻意練習,他推薦了Codewars(https://goo.gl/Tjmfqg),原因是:LeetCode可用來練習效能、演算法、資料結構,空間、時間、數學,而Codewars偏重於IDE、重構技巧、開發工法、Pair練習、Dojo/Kata題庫,以及熟悉語言特性。

就這點來看,也許就我的目的而言,該找個時間來玩玩Codewars,這不是為了面試,而是為了刻意練習某個對象,哪天真的想試著符合遊戲規則,而得在白板上寫演算法前,再刻意練習白板上的技巧就好了,面試過了很好,被刷下來,若檢討時,並非自己準備不足,我大概也是一笑置之。

作者簡介


Advertisement

更多 iThome相關內容