Steve Yegge:Google面試秘籍
我憋了很長時間想寫點關于去 Google 面試的秘籍。不過我總是推遲,因為寫出來的東西會讓你抓狂。很可能是這樣。如果按統計規律來定義“你”的話,這文章很可能讓你不爽。
為啥呢?因為啊……好吧,對此我寫首小詩回答:
哎媽呀,俺咋聽不懂涅
這個史迪威講的都啥啊
要是俺老板也腳底他對
俺的工作就得玩兒完啦
哎媽呀,哎媽呀.....
你們感受一下。
(本文作者:Steve Yegge,業界大牛程序員,Google 員工)
當我還在別的公司,剛開始寫點有關面試的東西的時候,我根本沒有意識到會有上面這種典型的對面經的反應。不過很快我還是發現了。
看吧,大概的情況會是這樣的:
我:blah blah blah, 我喜歡在面試里問X這個問題,blah blah blah…
你:X這個問題?哥們,我自打上大學就沒聽說過X!我的工作中也永遠不需要用到它!他在面試里居然問這個?不過這說明那里有人覺得知道它很重 要,而且,而且…我卻不懂這個!如果他們發現了我在這方面的無知,不僅我會被現在的公司無情地掃地出門,而且那些喜歡問X問題的面試官也都會拒了我!如果 人們都聽信史迪威的話,那所有的面試官都不會招我了!我將無家可歸,窮困潦倒!僅僅是因為我沒有懂一些我之前永遠用不上的東西!這太可怕了!我應該貶低X 這個東西,除此之外我并不想先找本書仔細研究明白它再去否定它。顯然我必須到處宣傳史迪威是如何愚蠢,這樣就沒人會聽他的了!
我:所以總體來說,blah blah… 嗯?你剛才說什么“掃地出門”?還有“窮困潦倒”?你在說什么啊?
你: 嗷!左一刀,右一刀,我刀刀不離你的后腦勺!
我: 好吧。我不會再談面試的事了。
到底X是啥并不重要。它可能是任意一個概念。我可能會這么說:“在面試中向應聘者發問真的感覺好爽哦”,可是應聘者們還是會被嚇壞了,因為他們對面試這檔子事或者對于自己的名字缺乏安全感。但愿是前者吧。
可是,然后呢,隨著時間流逝,面試者們來來去去,最后我們總是說:“天啊,我們真的希望剛才那位顯然很聰明的應聘者對于面試準備得更好一點。我們有什么辦法整點小秘籍來幫助未來的應聘者們呢?”
然后也沒誰真的去做點什么,因為我們都害怕被某些不懂X概念的人給兇狠地砍上幾刀。
我也考慮過只給出一套秘籍,里邊就用類似于X這樣的變量名而不是真正的主題,不過還是覺得在這樣產生的真空狀態下,每個人恐怕都會抓狂。不然的話,那個方法看起來還是挺不錯的,只要我用一個假名發布它就好了。
最后,應聘者們真的需要一些秘籍,不管看秘籍的時候會有多么揪心。所以,與其繞彎子扯閑淡,我還不如實實在在地告訴你們一些具體的重要的X概念,還有不少有關面試準備的信息。
附加免責聲明
本博客和 Google 無關。Google 不知道我在發布這些秘籍。這只是你我之間的事情,好不?別告訴他們我幫你支招了。你就直接去搞定面試,這樣咱倆都是正人君子。
這里我只談一般性的軟件工程師職位及相應的面試環節。
這些秘籍其實是通用的,沒有什么特別針對 Google 而不適用于其他軟件公司的東西。其實我早就可以寫點針對 20 年前我的第一份軟件開發工作的秘籍。也就是說,這些秘籍無關時間,至少在我們的職業生涯期間是無所謂的。
顯然這些秘籍本身也不會讓你得到工作。我的愿望是你遵循了這些秘籍能在面試中表現出你的最佳水平。
噢,呃,那么為啥要提到 Google 呢?
啊哈,你問我為啥提到 Google?好吧,那咱們就馬上開始對話吧,好不?
你:我應該去 Google 工作嗎?就因為他們說該去,還是有啥別的好處?我在那里會不會平安快樂?我是否應該馬上就申請?
我:是的。
你:該哪個問題了……等等,你說“是的”是什么意思?我都還沒告訴你我是誰呢!
我:哥們,答案就是“是的”。(你也可能是個女的,不過我還是要叫你哥們。)
你:可是……可是……我的惰性大到接近癱瘓的狀態,覺得在現在的公司呆著挺舒服的,或者說至少我已經對它不舒服的地方有了一定忍耐力。我認識這 里的很多人,而在 Google 我誰也不認識!我可能不得不去學習 Google 的 build 系統,還有技術什么的玩意兒!我在那里沒有任何的信任和聲譽,我可能必須要從頭開始!我等得太久了,而那里根本沒有上升空間!我害怕……
我:哥們,答案已經是“是的”了,對不?這是一個常量了。其他去 Google 的每個人當時也是處于和你一樣的境地,除了一小撮長著讓甘道夫都自慚形穢的大胡子的名人們。可是他們只是極少數而已。每個申請了的人都有和你一樣的不去申 請的理由。而且這里的每個人都會說:“天啊,我真的很高興來了這里工作!”所以只管申請就是了,不過要先準備好。
你: 可是,要是我被誤判了咋辦?我可能既聰明又稱職,可是因為某種說不清道不明的原因,我可能在面試里表現很差然后被拒!那對我幼小的心靈是多么巨大的打擊啊!與其接受失敗的幾率,我還不如完全放棄這個機會呢!
我:沒錯,這種估計至少是部分正確的。我第一次面試就基本沒搞定,不過我當時像條流浪狗一樣苦苦哀求,直到他們給了我第二輪面試的機會。我抓住他們心理脆弱的時機搞定了他們。在第二輪面試里,我預先準備好了,表現就大有改觀。
重點是,Google 有業內著名的假陰性率,這意味著我們有時候會拒掉合格的應聘者,因為這樣感覺比有時招進來不合格的人更好一些。這問題實際上在整個行業里都普遍存在,只是 比例在不同公司里有差別而已。在 Google,假陰性率是相當高的。我不太具體知道有多高,但是我確實知道很多聰明且合格的應聘者沒通過我們的面試。這是無奈之舉。
不過真正重要的道理是:如果你沒拿到 offer,你還是可能勝任來這里工作的。所以,不要為此給你幼小的心靈造成巨大的打擊。
我認識的任何人都知道,假陰性是完全隨機出現的,并且和你的技能或資質無關。假陰性結果可能來自一系列因素,包括但不限于:
- 你正好今天不爽
- 一個或更多面試官正好今天不爽
- 在你和一個或幾個面試官之間的溝通有一些微妙的問題
- 你不走運,碰到了面試敵對圈
啊不,不要碰到面試敵對圈!
是的,恐怕你需要擔心這個。
這是什么,你問我?好吧,回想我還在亞馬遜工作的時候,我們當時進行了(毫無疑問,他們現在也還在進行)大量的對于這個問題的研討。我們最終的 結論是每個亞馬遜的員工E都會有至少一個”面試敵對圈“:一批會在面試中拒掉E的其他的員工S。理解其根本原因對應聘者是很重要的,所以我會告訴你一些我 在這些年的發現。
首先,你不能告訴面試官什么重要什么不重要。在任何公司都不行。除非他們明確地征求你的意見。在一位工程師從大學畢業后,只有一年左右的非常窄 的時間窗口可以對其進行有關面試的教誨,在那之后時間窗口就會關閉,然后他們相信他們已經是一個”優秀的面試官“了,從此不再改變他們的問題,提問的風 格,面試的風格,或者他們提供反饋意見的風格,永遠不會再改變了。
這是個問題。不過我已經碰壁多次,不再嘗試(去改變他們的想法)了。
第二個問題:每個“有經驗的”面試官都有一套自己鐘愛的主題,還可能還有一些具體的問題他們認為可以用來準確判定應聘者的能力。任何兩個面試官的題庫可能會大相徑庭,甚至完全沒有交集。
一個隨處可見的典型例子是這樣的:面試官A總是考 C++ 細節,文件系統,網絡協議和離散數學。面試官B總是考 Java 細節,設計模式,單元測試,Web 框架和軟件項目管理。對于任意一個給定的應聘者,如果面試官A和B都在面試圈里,他們很可能會給出非常不同的評價。其實如果碰巧的話,當年A和B甚至很可 能都會在面試中互相拒掉對方,但正好他們應聘的時候碰到的都是面試官C,他給倆人出的題是有關數據結構,Unix 實用工具以及進程和線程,對這些A和B正好都在行。
那幾乎就是你從一個高科技公司拿到 offer 時所發生的一切:瞎貓碰到了死耗子。由于這種先天有內在缺陷的面試過程,很有可能某個在面試圈里的人會對你印象不佳,即使你就是阿蘭·圖靈。實際上,如果你是阿蘭·圖靈就更為不妙,因為這意味著……顯然,你不會C++。
這里的底線是,如果你要去參加任何軟件公司的面試,你必須做好預案以應對你走背字的情況,屆時你會碰到一個或多個你的面試敵對圈人士進入你的面 試官行列。如果這種情況出現了,你會努力再努力,然后被告知你這次不適合申請的崗位,然后你會感到不爽。只要你不是覺得極其不爽,事情就沒啥大不了的。你 應該為發生了這樣的事情后你覺得不爽而高興,因為啊,這說明你是正常人類。
之后,你應該等上 6 到 12 個月然后再申請。那基本上是我(或者我認識的任何人)所能想出的對付假陰性問題的最佳解決方案了。讓我們忘記過去,從頭再來。這里有很多人都是在第二次或第三次嘗試時被錄用的,他們現在都干得很不錯。
你也能做到的。
對了,對于潛在的被拒風險我感覺好多了。
不錯!那就讓我們開始了解這些秘籍吧。
如果你剛才讀的夠仔細的話,你會意識到我就是面試官D。這說明我個人偏愛的問題和主題不過是我個人的,和其他人的偏好相比,談不上好也談不上 差。所以我沒法告訴你這些問題和主題是什么,無論我是多么愿意告訴你。因為這樣做會得罪喜歡其他問題的面試官A,B,C…一直到面試官X。
恰恰相反,我想幫你準備好一些常規話題,這些話題我相信在類似于 Google 的公司里絕大部分的面試官都會用到。大概說來,這種公司會自己開發很多軟件,并且進行大量的分布式計算。也有其他的一些技術公司,反差最大的哪一類是把所 有事情都外包給顧問,并嘗試使用盡可能多的第三方軟件的那些公司。我的秘籍僅僅對類似于 Google 的公司有效。
所以你可能也可以把它當做就是 Google,對不?
首先,我們來討論非技術性的準備。
熱身
沒人會不熱身就走上拳擊臺。秘籍:你可以帶著拳擊手套去參加面試。不,等等,不好意思,我的意思是說要提前熱身。
如何熱身呢?它基本上可以分成短期熱身和長期熱身,兩種你都要進行。
長期熱身的意思是:在面試前花一到兩星期進行學習和練習。你需要讓你的思維進入在白板上解答問題的一般“模式”。如果你能在白板上搞定問題,所有其他的媒介(筆記本電腦,共享網絡文件,以及其他)就是小菜一碟了。所以要以白板為主攻方向。
短期熱身的意思是:在面試前一天晚上充分休息好,然后在面試當天的上午做大量快節奏的熱身(譯者注:就是做題)。
我所知道的兩個最好的長期熱身方法是:
1)找一本數據結構和算法的書復習。為什么?因為這最有可能幫助你提升識別問題的能力。當你不需要更多解釋 就理解了面試官問題是哪一大類的時候,很多面試官都會覺得滿意。例如,如果他們問你一個有關用不同顏色填充美國地圖上各個州的時候,如果你認識到這是一個 圖論里的涂色問題,你會得到加分,即使你已經不記得涂色算法是怎么弄的。
如果你記得它是怎么弄的,那你可能會很快搞定答案。所以從面試準備角度來說,你最好的準備工作就是練習識別問題的技巧,弄清每類問題最適合用哪些算法和數據結構來解決。
對于這類面試準備我絕對鐘愛的是 Steven Skiena 寫的那本《算法設計手冊》。對于我理解圖問題是多么驚人的普遍存在(和重要)方面,它比其他任何書都更有幫助,所以我覺得每個程序員的工具箱里都應該有一本。這本書也介紹了基本的數據結構和排序算法,也算是物超所值了。不過真正的金礦在該書的后半部分,里邊是單頁的百科全書,覆蓋了無數有用的問題以及解答它們的各種方法,簡明扼要。幾乎每個單頁都有一個簡單的圖片,使之易于記憶。這對于學習如何識別數以百計的問題類型是一個很棒的方法。
我認識的其他面試官推薦《算法入門》。這是真正的經典和無價之寶,不過復習它你可能需要多于兩周的時間。如果你想胸有成竹地去面試,也可以考慮推遲你申請的時間,直到你掌握了該書的精髓為止。
2)找個朋友模擬面試。該朋友要隨機地問你一些面試題,你則在白板上寫出解答。不管你覺得多么疲勞或懶散,堅持做完所有面試題。只要你能承受就盡可能多地模擬。
在我第一次去 Google 面試前我沒做過這兩種準備,結果我非常震驚地發現我在白板編程時表現得巨差無比,因為我已經 7 年沒參加過面試了。這很難。而且,我曾經知道或者至少聽說過的一堆算法和數據結構都全忘光了。
通過花一周時間進行上面這些練習,我就對第二輪 Google 面試準備得很充分了。然后我在第二次面試里的表現就大有改觀。是這些練習改變了一切。
對于短期準備,你能做的無非是讓自己盡可能保持狀態。不要沒熱身就開始。先解答一些問題,瀏覽你的復習材料。喝點咖啡,它有助于讓你思維更敏 捷。信不信由你,反正我是信了!確保在你開始面試前至少花了一個小時進行練習。把面試當做一場體育比賽或者音樂會,或者一次考試,總之,如果你先熱身了, 那么你就能表現出最佳狀態。
心理準備
好了!你現在是一位編程高手,有一長串的成就。現在是忘記所有這一切而只關注通過面試的時候了。
你必須以謙虛、開明和專注的形象出現。
如果你表現出傲慢,面試官會琢磨他們是否愿意和你一起工作。最常見的傲慢表現就是質疑面試官提出問題的合理性,這無疑會讓他們不爽,正如我之前指出的。記得我說過你不能教面試官如何面試嗎?沒錯,如果你是應聘者,這一點更是真理了。
所以,別這么問:“天啊,算法真的那么重要嗎?你在現實生活中有過需要那么干活的情況么?我永遠不需要去干那樣的活。”你這么問只會被拒,所以別問那樣的問題。把每個問題都當做合理的來看待,即使你因為不知道如何解答而備感沮喪。
如果你鉆到牛角尖里出不來了,可以尋求幫助或提示。有些面試官會因此給你減分,不過,面對那些可能讓你陷入半小時可怕的沉默的問題,這么做偶爾能幫你突破一些困難,讓你得到優秀的成績。
當你在思考的時候嘴里別念念有詞。
不要試圖改變主題去回答一個不同的問題。不要試圖通過講戰爭故事轉移面試官的思路,讓他沒法問你問題。不要試圖恐嚇你的面試官。你應該專注在他們問你的每個問題,盡全力完整地解答它們。
有些面試官不會硬性要求你寫代碼,不過他們往往期望你在解答過程中某個時間會在白板上寫代碼。他們會提示你,但可能不會直截了當地說:“現在我要求你在白板上寫一些代碼。”如果你不確定,你應該問他們是否希望看代碼。
不同的面試官對于代碼的要求也相去甚遠。我自己是不太在乎語法的(除非你寫的東西明顯不可能在任何編程語言里實現,這時候我會插話,確認你實際 上并不是馬戲團變戲法的小丑,而這部分代碼的確是錯的)。可是有些面試官對于語法是很挑剔的,有些甚至會因為你少寫了個 ; 或者 } 就默默地把你否了,而且還不告訴你。我認為這些面試官是…..好吧,這是個技術性詞匯,和“魂淡”發音差不多,可他們覺得自己是絕頂的技術評估高手,而且 咱也沒辦法和他們說理呀。
所以還是要問。問他們是否重視語法,然后,如果他們重視,盡力把語法寫對。從不同角度和距離仔細檢查你的代碼。假裝這是別人的代碼,而你被安排 來發現其中的 bug。當你站在距離白板 2 英尺的地方,而面試官盯著你的肩胛骨的時候,你會驚奇地發現自己居然會在某些地方出錯。
問一些澄清的問題是可以的(而且是相當受鼓勵的),偶爾和面試官確認一下你解答的思路是正確的。如果你聽完問題就跳起來開始寫代碼,即便你寫對 了,有些面試官還是會給差評。他們會說你沒有先考慮清楚,而且你是那種“咱用不著做設計”類型的牛仔程序員。所以即使你覺得你知道問題的解答方法了,在一 頭扎進去之前最好先問一些問題,并討論一下你打算采用的方法。
在節奏方面,不要在實際解答問題之前消耗太多時間,不然一些面試官會給你耽誤時間的罰分。盡可能快地解答和寫代碼,因為面試官通常都希望在面試 中多考一個問題,如果你解答第一個問題太慢,他們就沒有時間再考了。他們會把你否掉,因為他們沒法完整地了解你的技能。在面試中很少看到爭議帶來的好處。
最后一個非技術秘籍:隨身帶著你自己的可擦除白板馬克筆。在辦公文具店里有那種細筆芯的馬克筆賣,而大部分公司(包括 Google)基本都買的那種粗筆芯的。細筆芯馬克筆可以把你的白板從 480i 標準清晰度顯像管變成 58 英寸 1080P 高清等離子體液晶屏。在面試中,你需要所有能獲得的幫助,而充分的白板空間是一個真正的福音。
你也需要練習白板空間管理技術。例如,不要從右邊開始一直把代碼寫道右下方的角落,最后寫成了蠅頭小字。你的面試官不會對此留下好的印象。有意思的是,雖然我對應聘者這么干很生氣,我自己面試的時候也這么干過。當心這個問題。
哦,還有,別站在那里揮舞你的馬克筆,它會揮發最后變干的。我這是在提醒你:盡可能減少面試中讓人分心的事情,而那也是不可思議的常見的例子。
好了,非技術秘籍告一段落。現在來說說X,給X賦點值!別砍我啊!
技術性準備秘籍
最好的秘籍是:去讀個計算機科學的學位。你有的計算機科學知識越多越好。雖然你并不一定必須有計算機專業的學位,但它對你應聘有利。你也不一定非要有個研究生學歷,但它也對你應聘有利。
不過,這是 2 到 8 年之后的事了,你很可能在考慮在更早一點的時間申請 Google 的工作,所以下面是一些短期的秘籍。
算法復雜度:你需要知道O()的概念。必須滴。如果你還在苦苦掙扎于理解基本的算法復雜度分析概念,那你基本上肯定無緣這份工作了。這個概念應該是計算理論教材最開頭一章的內容,所以趕緊去學吧。你能行的。
排序:知道如何排序。不要用冒泡排序。你必須知道至少一個n*log (n)復雜度排序算法的細節,最好知道兩個(比如,快速排序和合并排序)。合并排序在快速排序不適用的情況下會非常有用,所以要好好看一下。
看在上帝的份上,不要在面試中試圖對一個鏈表進行排序。
散列表:按理說散列表是人類所知的最重要的數據結構了。你絕對必須了解它們的原理。同樣,這也會占數據結構書里的一章,所以要去好好學一下。你必須能在一次面試的時間里,用你最喜歡的語言,做到只用數組去實現一個散列表,
樹:你必須了解樹結構。我要說的是:這是基本的東西,其實在這里提起它顯得挺沒檔次的,可是你們中的一些人啊,竟然不知道基本的樹的構造,遍歷和其他操作算法。你最起碼最起碼必須熟悉二叉樹,N叉樹,還有字典樹。樹結構很可能是你們長期熱身練習最好的練習題來源。
你必須熟悉至少一種類型的平衡二叉樹,無論是紅/黑樹,伸展樹還是 AVL 樹。你必須準確地了解它是如何實現的。
你必須了解樹的遍歷算法:廣度優先和深度優先,并知道中序、后序和前序的差別。
你每天可能不會用到很多樹結構,但是如果真的是這樣,那只是因為你在回避樹結構問題。一旦你學會了它的原理,你就無須再那么做了。學吧!
圖
圖結構是非常非常重要的。比你想象的還要重要。即使你已經覺得它很重要,可能它實際上比你想的還要更重要。
在內存中表達圖有三種基本形式(對象和指針,矩陣,以及鄰接表),你必須了解每一種形式并知道各自的優缺點。
你必須了解基本的圖遍歷算法:廣度優先搜索和深度優先搜索。你必須了解它們的計算復雜度,它們的權重,以及在真實代碼中如何實現。
你必須嘗試學習更潮的算法,例如 Dijkstra 和A*,如果你有機會的話,它們在任何地方用都很好,從游戲編程到分布式計算,隨你說。你必須了解它們。
任何時候別人給你一個問題,用圖結構去思考。圖結構是最基本和最靈活的表達任何關系類型的方式,所以任何有意思的設計問題都會有 5 成可能要用到圖結構。在轉向其他解決辦法之前,先完全確定你想不出用圖結構解答它的辦法。本秘籍非常重要。
其他數據結構
你應該學習盡可能多的數據結構和算法,直到你的腦袋裝滿為止。你應該特別了解 NP 完備性問題中最著名的幾類,例如旅行銷售員問題和背包問題,能在面試官隱蔽地問到你這類問題時把它識別出來。
你必須搞明白 NP 完備性是什么含義。
總體來說,努力學習數據結構,嘗試盡可能多記,這總是沒錯的。
數學
有些面試官會問基本的離散數學問題。在 Google 這類問題比在我呆過的其他地方更流行,我覺得這是件好事,雖然我在離散數學方面也不是特別牛。我們身邊都是計數問題,概率問題,和其他離散數學的問題,而 我們身邊那些不懂數學的人在輕率地編一些他們自己都不知道是什么的程序。
如果面試官考你數學題,別抓狂。盡最大努力去做。如果你在面試之前花點時間復習組合數學和概率論的話,你的最大努力會更得力。你應該熟悉n選k問題以及同類的問題,越多越好。
我知道了,我知道了,你沒多少時間。不過這里的秘籍能幫你實現從“我們不太確定”到“我們招她吧”的飛躍。而且情況也不是都那么糟糕,離散數學 沒用到多少你學過又忘了的中學數學。它其實是起始于小學數學然后擴充出來的,所以你很可能通過幾天的努力學習重新撿起面試需要的那些知識。
很遺憾,對于離散數學教材我沒有什么好的推薦,如果你有,請在評論里提出。謝謝。
操作系統
這是我補充的一點,它讓你了解進程、線程和并發問題。很多面試官會考那些概念,而且這是很基本的,所以你應該了解它。要了解鎖、互斥、信號和管 程,以及它們的工作原理。要了解死鎖和活鎖以及如何避免它們。要了解進程和線程分別需要什么資源,context 切換如何進行,它們在操作系統以及底層硬件是如何初始化的。了解一點計劃任務。世界正向多核系統邁進,如果你不了解現代并發架構的話,你很快就會變成落后 于時代的恐龍。
對于該主題我自己讀過的最好最實用的書是 Doug Lea 寫的《Java 并發編程》。它里邊每一頁都令我拍案叫絕。顯然還有很多其他關于并發的書。我一般會躲開太學術性的,專心于實用的東西,因為這些概念最可能被在面試中考到。
編程
你必須精通一門編程語言,最好是 C++ 或者 Java。 C#也行,因為它和 Java 非常相似。至少在一些面試中,你需要寫一些代碼。你應該對你擅長的編程語言了解很多細節。
其他事務
由于我在之前闡明的一些規則,你還是有可能碰到面試官A,你按我的秘籍復習的東西沒有一樣用得上(除了熱身以外)。如果是這樣,就盡最大努力去 做。即使碰到最壞的結果,你還總是可以過 6 到 12 個月再殺回去,對不?看上去這時間挺長,不過我向你保證它會一閃而過。
實際上,我談及的內容大部分是警示性的:如果你不了解它那就大事不妙了。離散數學也許是可選的,不過你如果不了解最基本的東西也有點危險。我提 到的其他所有東西你都應該了解,然后你至少要準備到基準面試的水平。在實際面試中出的題可能會比基準面試難很多,也可能會容易一些,基本上取決于面試官的 情況。
這就看你有多幸運了。你感覺要走運了?那就去試試唄!
英文原文:steve yegge,編譯:@老碼農的自留地