我憋了很長時間想寫點關於去Google面試的祕籍。不過我總是推遲,因為寫出來的東西會讓你抓狂。很可能是這樣。如果按統計規律來定義“你”的話,這文章很可能讓你不爽。
為啥呢?因為啊……好吧,對此我寫首小詩回答:
1 2 3 4 5 |
哎媽呀,俺咋聽不懂涅 這個史蒂夫講的都啥啊 要是俺老闆也腳得他對 俺的工作就得玩兒完啦 哎媽呀,哎媽呀..... |
你們感受一下。
(本文作者: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,你還是可能勝任來這裡工作的。所以,不要為此給你幼小的心靈造成巨大的打擊。
我認識的任何人都知道,假陰性是完全隨機出現的,並且和你的技能或資質無關。假陰性結果可能來自一系列因素,包括但不限於:
1 2 3 4 |
你正好今天不爽 一個或更多面試官正好今天不爽 在你和一個或幾個面試官之間的溝通有一些微妙的問題 你不走運,碰到了面試敵對圈 |
啊不,不要碰到面試敵對圈!
是的,恐怕你需要擔心這個。
這是什麼,你問我?好吧,回想我還在亞馬遜工作的時候,我們當時進行了(毫無疑問,他們現在也還在進行)大量的對於這個問題的研討。我們最終的結論是每個亞馬遜的員工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個月再殺回去,對不?看上去這時間挺長,不過我向你保證它會一閃而過。
實際上,我談及的內容大部分是警示性的:如果你不瞭解它那就大事不妙了。離散數學也許是可選的,不過你如果不瞭解最基本的東西也有點危險。我提到的其他所有東西你都應該瞭解,然後你至少要準備到基準面試的水平。在實際面試中出的題可能會比基準面試難很多,也可能會容易一些,基本上取決於面試官的情況。
這就看你有多幸運了。你感覺要走運了?那就去試試唄!
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式