03.02 如何在谷歌擁有一張辦公桌?谷歌八年高級工程師親授面試經驗

選自github.io

作者:Pablo Samuel Castro

機器之心編譯

參與:李詩萌、張倩、蛋醬

春招來臨,「如何拿到大廠 offer」成了每個求助者最關心的問題。在本文中,谷歌大腦高級軟件工程研究員、強化學習框架「多巴胺」(Dopamine)作者 Pablo Samuel Castro 分享了他拿到谷歌 offer 的經驗。這份「谷歌面經」不僅適用於谷歌的軟件工程師職位,對申請其他公司的軟件工程師及其他職位(如研究科學家)也有幫助。


如何在谷歌擁有一張辦公桌?谷歌八年高級工程師親授面試經驗


大家經常問我,怎麼才能拿到谷歌的 Offer?雖然這個問題沒有固定答案,但我還是有一些可以幫助其他人(包括我自己)的技巧。


如何在谷歌擁有一張辦公桌?谷歌八年高級工程師親授面試經驗


我在谷歌的面試過程不算完美,但我確實感覺整個過程都很好、很客觀。無論結果如何,請記住:你的個人價值不該由你是否得到了 offer 來定義。


引言


我應該申請谷歌的職位嗎?這是另一個常見問題。答案几乎總是肯定的!去谷歌面試不僅可以測試你的極限,還能讓你發現自己的不足。如果你嘗試過,就算最後沒能成功,我也保證你會成為更加強大的程序員和麵試官。


在獲得 PhD 學位後,我立志成為一名學者,但那時(大概是 2011 年)的就業市場真的非常糟糕。在上司的建議下,我申請了谷歌的職位。這是我申請的唯一一份業界工作,也是我在業界最感興趣的工作。


在提出申請後,我為面試做了許多準備。我確信,如果申請的那天就進行面試,我是無法通過的:花時間準備面試是非常必要的。到面試時,我感覺自己已經準備得非常充分了。


最終,努力得到了回報:我收到了加入谷歌匹茲堡辦公室的 offer,從 2012 年起,我成為了一名谷歌軟件工程師(SWE)。


如何在谷歌擁有一張辦公桌?谷歌八年高級工程師親授面試經驗

我在谷歌匹茲堡辦公室的第一張辦公桌。


如何申請谷歌?


你可以訪問谷歌求職網站找到合適的職位:https://careers.google.com/;


推薦一般也有用。如果谷歌有你認識的人,可以請他們內推。如果你不認識任何在谷歌工作的人,而且你已經申請了一段時間,但仍沒有收到任何迴音,可以發簡歷給我,看我能不能幫上忙。請注意,這種做法依然無法保證你得到面試機會。我不太清楚面試篩選標準,因此無法在這方面給出建議。


如何準備谷歌面試?


面試(至少)包括三個部分:編程、算法和數據結構,以及個人品質。谷歌(和其他公司)經常舉辦面試研討會,你可以在會議中進行模擬面試;如果有條件的話可以搜索並加入這些研討會。


編程


你要能寫出函數式代碼。而且理想情況下,你寫的代碼要可以立即編譯或運行。語言不重要,但你要指定面試時想使用的語言。因此,要確保你非常瞭解自己選的這門語言。此外,偽代碼不是一種語言。


1. 用 Barebones 編程


如果你寫代碼時依賴 IDE,請試著用 barebones!無論你用什麼程序寫代碼,請關閉語法高亮和自動補全功能。嘗試用什麼都沒有的 vim 寫所有代碼(即便是現在我還是在用非常簡單的 vim 寫大多數東西,包括這篇文章)。你也可以用 Emacs。


2. 熟能生巧


我在準備面試時,主要用 C++ 寫打碼,所以我決定專注於此。我發現了一個在線的編程比賽,這個比賽有之前比賽的記錄,這樣可以「假裝」正在比賽。好處在於,這個在線服務可以以編程方式檢查代碼的語法和算法的正確性。經過努力練習,我終於從頭寫出了可以編譯及解決問題的 C++ 代碼。在此之前,我重複了千千萬萬遍。


此外,我還花了好長時間搜尋需要的庫,以及如何執行正確的 I/O 等。


我不記得用過哪些網站,但 topcoder 中有針對實踐問題的部分,似乎可以達到相同的目的。


topcoder 地址:https://arena.topcoder.com/#/u/practiceProblemList


也可以瀏覽 glassdoor 這樣的網站,網站中有大量過去的谷歌面試題。試著解出所有的題。


glassdoor 地址:https://www.glassdoor.ca/index.htm


3. 在白板上寫代碼


試著在白板上寫代碼(如果你沒有粉筆或白板,也可以在一張紙上手寫)。在白板上寫代碼的感覺截然不同,但谷歌面試中有這項要求。


有經驗當然最好。我建議你在白板上寫完整的程序,然後再在電腦上編碼,並確保可以一次編譯或運行成功。如果無法成功,請再試一次。


讓別人圍觀你在白板上寫代碼也非常有用,可以幫助你適應可能出現的緊張情緒。


有幾處語法錯誤是可以接受的,但如果代碼太粗糙,而且錯誤過多,面試官可能會覺得你不熟悉自己選的語言。


算法和數據結構


我準備面試時看的書也是我讀大學時用的書——Thomas H. Cormen、Charles E.Leiseron、Ronald L. Rivest 和 Clifford Stein 寫的《算法導論》(Introduction to Algorithms)。我肯定,還有很多書都可以幫你達到相同的目的,只不過這是我隨手就能拿到的書。


有一些算法和數據結構是你絕對要知道且熟悉的:


  1. 排序:瞭解不同的排序方式。知道各種排序算法的適用場合及複雜性。
  2. 鏈表:什麼是鏈表?你能否從頭寫出一個鏈表?插入、刪除和搜索的複雜度是多少?什麼時候使用鏈表?鏈表是否有不同的類型?
  3. 哈希:什麼是哈希函數?怎樣的哈希函數稱得上好的哈希函數?什麼是哈希衝突(collision)?如何解決衝突?平均複雜度是多少?最壞情況下的複雜度是多少?
  4. 二叉樹:什麼是二叉樹?你能從頭寫出一個二叉樹嗎?什麼是二叉搜索樹?搜索、插入、刪除的複雜度是多少?平衡樹意味著什麼?複雜度是多少?
  5. 動態編程:什麼是動態編程?何時用動態編程?你是否會用動態編程算法解決問題(你可以從書中挑選一個例子進行練習)?
  6. 圖算法:圖的遍歷算法(BFS/DFS)。有向圖和無向圖。你能從頭寫一個圖數據結構嗎?什麼時候用圖?修改圖有哪些不同的方法?


上面列出的內容並非可能考到的全部內容,但我認為這是一個合理的基礎。我希望你知道上述所有問題。


和編程一樣,這部分的重點也是熟能生巧。解決不同問題時,請在思考後使用最適合的數據結構。


前面已經提示過:無論寫什麼樣的代碼,都要進行復雜度分析(即 big-O)。我個人總是在面試者寫完代碼後問他們這個問題,因為這表示他們可以分析自己實現代碼的效率。本文後面的內容會提到,即便你只能提供一個非常簡單的解決方案,但如果你能進行準確的分析,也會有很大的幫助。


個人性格


這是很難準備的一部分,但也很重要。面試官會問自己的問題之一是:我想和這個人一起工作嗎?如果你是個天才,任何扔給你的問題都能解決,但你卻在面試期間表現得像個混蛋,聘用你的可能就很小了。


在這方面,我也不能建議你做什麼樣的具體準備,但在面試過程中要記住幾點。


面試中


如果你已經安排進入面試了,首先要恭喜你,這已經很了不起了,因為不是每個人都能參加面試。這些重點你要記住:


將面試視為一次平等的對話,而非單方面的詢問。儘管在面試的雙方是權力不對等的,但我們並不是要騙你或者讓你犯錯。事實上,我們大多是在默默為你加油。


說出你的思考過程。確保將頭腦的思路過程清晰地展示出來,尤其是在白板上寫代碼之前。作為面試官,我們需要一些證明你表現良好的證據,說明白你的思路就有助於我們收集證據。此外,如果你陷入了一些我們認為不值得花太多時間的問題,我們可以及時幫你拉回來。如果你不說話,而直接寫了錯誤的代碼,我們無法知道你是真的不懂,或只是誤解了問題。另一方面,如果你默默寫出了完美的代碼,我們也不知道你是真的明白,或許你只是見過這個問題。


簡單的解決方案是很好的起點。不要勉強自己想出最高效的方法,先給出簡單的方案是很好的策略。


為什麼這麼說呢?原因有很多:


  1. 即便這個問題看起來微不足道,但也經常有一些意料之外的棘手情況。通過簡單的方案更容易解決這樣的問題;
  2. 簡單的方案可以很快地寫在白板上,有利於面試官評價你的表現;
  3. 簡單方案的複雜度分析比複雜方案的複雜度分析要容易得多;
  4. 簡單方案可以快速寫出來,之後就可以轉向尋找更復雜的解決方案,但你至少有一個可以作為基準的簡單方案;
  5. 對面試官來說,理解簡單方案比理解複雜方案更容易。你肯定希望面試官能理解你的方案,如果一個複雜方案讓面試官都困惑了,不利於得分;
  6. 過一遍簡單方案相當於對代碼進行「手動分析」,有助於你挑出冗餘的工作,還可以優化代碼;
  7. 簡單的方案也可以是深入交流的開始。既然已經有了一條解決方案,然後你就可以詢問面試官,是否想要更好的方案;
  8. 最後,要確保你已經告知面試官,你是以一個簡單方案開始(不代表你只能給出簡單方案)。


可以簡化假設。做一些簡單的假設能幫你更清晰地思考問題,原理和「給出簡單方案」類似。這個的好處在於可以表現出你有解構問題的能力,代表你能分辨出可能會造成嚴重問題的部分。


使用測試示例。找一些可以測試代碼的測試示例,試著預測邊際情況(例如空列表、越界索引、預料之外的特殊字符等),這樣有助於保證代碼的準確性,也有利於征服面試官。舉例真的很有用,面試官甚至可能會添加一些測試示例來檢驗你可能遺漏的其他邊緣情況。


花幾分鐘整理思路。我雖然建議你講出思考過程,但也不用勉強自己一直講話,尤其是在你還沒整理好思路的情況下,不停講話就可能導致你進入誤區。可以提出申請「我能花兩分鐘整理一下思路嗎?」,重要的是要讓面試官知道你在幹什麼。如果你覺得整理思路的時間太長,可能是因為你對問題的某一部分感到困惑,這就是下一個問題。


可以尋求幫助。如果感到困難,你可以尋求幫助,但要具體說明問題在哪。一般可能是你誤解了問題,所以沒能注意到問題中重要的點,有時也可能是面試官自己忘了提到問題中重要的部分。我就遇到過這種情況,面試者似乎被難住了,但我給了一點幫助後,他們就解決了問題。


可以有所不知。我參加面試時,實現了一個自定義數據結構,來簡化解決方案中剩下的代碼。面試官問我:「你為什麼不用映射?」,我告訴他「我不知道什麼是映射」。面試官很快在白板上給我解釋了映射的語法(這是比我的「用戶數據結構」更簡潔的版本),然後我就更快地解決了問題。我不知道是否因為承認自己的無知而得分,但最終得到了這份工作。


沒有「唯一正確」的答案。至少在大部分面試中都沒有唯一正確的方案,我最喜歡的是可以快速陳述、易於理解、同時存在簡單解和複雜解、而且很容易就能變複雜的問題。我認為大多數面試官都會問這些問題。這意味著我們並沒有預設答案,你只要盡你所能就可以了。


不要問你給出的答案是否正確。最好是用測試用例驗證你給出的答案,並根據測試結果證明答案是正確的。


可以有分歧。和麵試官有分歧沒關係,但是要用禮貌的方式表達。用具體工具(比如代碼和測試用例)支持你的觀點;如果只有口頭討論可能會引起誤會,這樣會消耗有限的時間。試著理解面試官的觀點(儘管他們看起來是錯的),並冷靜地讓面試官理解你的觀點。


將每次面試都視為一個嶄新的開始。如果你覺得哪次面試很糟糕,請將它擱置在一邊,或者等一切都結束後再想,然後開啟下一次面試。我知道這說起來簡單做起來難,但你得明白,下一次的面試官不會知道你之前的表現。就算你有一次面試的成績很糟糕,但你也可能通過下一次面試。


如果有時間,提點問題。我一般都在最後給面試者留出時間,讓他們問一些有關在谷歌工作的常見問題,比如你的角色或經歷等。如果你有問題,也許表示你對這份工作確實很有熱情。如果你沒有問題的話,那可以向面試官請教,可以請問他們在谷歌的角色和經歷。不要問「我在面試中要怎麼做?」或「正確答案是什麼?」這樣的問題,因為我們不會回答這樣的問題,這可能會使場面變得尷尬。


面試後


再一次恭喜,你已經完成了面試。後續過程大致是這樣的:


每個面試官都會給你寫反饋,給出「建議錄用」或「不建議錄用」的意見。面試官之間看不到其他的反饋。


你的資料中會包括:簡歷、面試反饋、過去的面試結果等,會有幾個招聘小組審查這些資料。這些小組由一些沒有面試過你的谷歌員工組成,他們會根據你的檔案袋給出錄用建議。


根據招聘小組的決定,可能會發生以下幾種情況:


  1. 你拿到了 offer;
  2. 你需要進行額外的電話面試。這不一定意味著你的面試表現不夠好,還可能是在面試過程中未能正確評估某種能力;
  3. 可能會讓你擔任其他職務。這並不是件壞事,這隻意味著招聘小組根據資料,認為你更適合擔任其他職位。此間也會有一些附加面試,歸根結底也是件好事;
  4. 你沒能得到 offer。這有點遺憾,在谷歌拿到 offer 確實不那麼容易,但你為這次面試所做的努力,以及這次面試經歷本身,都會在其他面試中幫到你。另外,一年後你也可以重新申請谷歌職位。我曾審查過某人的資料,他起初沒有得到 offer,但在一年後重新提出了申請,最終得到了 offer。


寫在最後


儘管本文所寫大部分都是關於谷歌 SWE 職位的面試,但這些建議也適用於其他公司的 SWE 職位。幾年前,我參加了 Shopify 的面試,也用過文中提到的所有技巧。最後我得到了 offer,但因為我受邀加入 Google Brain(我現在很高興地在這裡工作),所以拒絕了 Shopify 的 offer。


這篇文章也能從某種程度上幫到非 SWE 職位的求職,其中我最熟悉的就是研究科學家(RS)職位。我曾主持過一些 RS 求職面試,但還不足以提供具體的指導。但我想說的是,即便是面試 RS,你也要通過編程面試。我曾在編程面試中遇到過理論很強但實操很弱的人,最後我給了「不予錄用」的建議(這個人沒加入谷歌,我也不知道他是否拿到了別的 offer)。


此外,還有一些其他人分享的很有價值的建議。如 Mekka Okereke和 Steve Yegge都分享了一些很好的建議。還有人推薦了《程序員面試金典》(Craching the Coding Interview)這本書。


原文鏈接:https://psc-g.github.io/interviews/google/2020/02/25/interviewing-at-google.html


分享到:


相關文章: