Last updated on February 5, 2023
這幾年來遇過不少面試,當過面試者也當過面試官。這篇就從我自己的經驗出發,講講在程式面試時,我身為面試官會希望看到怎樣的面試表現,同時這也是我自己去面試時所採取的策略。
更多面試經驗相關文章:《Google Facebook Quora LinkedIn AirBnb 面試經驗分享》
兩大能力
面試時我主要看兩大能力:技術能力與溝通能力。前者很好理解,就是大家常說的解題能力,網路上大部分的訓練都是這方面的。而後者常被忽略卻一樣重要,也是我常常看到面試者缺乏的地方,所以這裡多講一點。
我會希望面試者在整個面試過程中都能主動且清楚講出自己的想法,這樣面試官才能知道你什麼會什麼不會,如果面試官想幫你才有辦法給提示。最糟糕的情況就是一個人憋著半天不說話,然後突然說自己不會或者噴出一個最佳解卻不解釋。
只說不會的話,我也不知道你是哪裡不會而愛莫能助。直接噴出最佳解的話,因為沒有推理過程所以也很難知道你的思路過程,甚至有背答案的疑慮。
歸根到底,面試是想找人進入團隊一起天天合作解決問題。假如一個人有想法卻常常憋著不說,這會使溝通成本變得非常高,想幫也幫不了,而共事就會極度缺乏效率,整天在辦公室讀空氣就飽了。每次在決定面試結果時,我都會問自己:是否會想跟此人一起工作?
七個階段
下面是程式面試的主要七個階段,我用經典題『Leetcode 215. Kth Largest Element in an Array』 來當例題。而每個階段也會有建議與不建議的做法當作參考,分別用綠色與紅色的區塊來表示。
寫 Leetcode 時可以參考這個模板來增加效率:《記性差的人如何有效率地用 LeetCode 刷題?我跳槽用的筆記模板分享以及圖文教學》
搞清楚題目
第一步也是最重要的一步就是:搞清楚題目在問什麼!如果誤會了題目,那你的解法再神也沒用。絕對不要自己隨便假設題目沒說的,有疑問就一定要提出來!
有些題目甚至是設計來希望你提問的:畢竟真實的工作中,我們常面對的是沒有定義好的問題,因此定義好問題本身也是一項重要的能力。
問題定義包含題目的輸入與輸出,邊界條件之類的。遇到不清楚的邊界,就要問面試官該怎麼處理,因為這也是希望你去發現並提問的。有時面試官會反問你該怎麼處理(我就常這樣),此時就要提出合理的處理方案通常就沒問題。
一個建議是這裡可以設計幾個測資,然後向面試官確認這些測資是否正確。這個可以有助於確保題目理解正確,在後面的步驟也可以拿來測試程式的正確性。
Do
我的理解是,給定 N 個未排序的任意數字,找出第 K 大的數字。這個理解是否正確呢?
所以如果今天輸入是 [1, 3, 0, 2, 4] 而 K = 2,我的程式應該要輸出 1 對吧?
Don't
(心中想:題目沒說這些數字是否排序過,我就假設它是吧,這樣比較簡單!)我對題目沒有問題,解法是 blablabla。
討論可能的解法
題目確定後才開始思考解法,這裡的關鍵在於你是否能夠有系統地一步一步解決問題,並且講出來讓旁人跟上並理解你的思路。Speak out loud!
切忌直接拋出結論,而省略推理過程,雖然福爾摩斯說這樣很酷,但畢竟這是面試而不是在跟華生聊天所以別這麼幹。就像上面說的,面試時推理過程與結論一樣重要!同時也切忌急著去寫扣,方向確定後再寫扣才不會事倍功半。
Do
如果這個數列是有序的話會簡單很多,因為定義上有序數列的第 K 個數字就是答案,所以一個簡單解法是排序整個數列。而也有另一個做法就是用 Heap,就是 blablabla。
Don't
排序就解決啦,可以開始寫扣了嗎?
分析並總結所有解法
常常可行的解法不只一種,這種情況下最好通通都講出來,並且主動分析各個解法的優缺點,讓面試官知道你是有考慮到這些的,所以重點是主動。分析完,得到面試官同意才開始寫扣!如果沒同意,代表你目前提出的方案可能不夠好,最好再想想是否漏了什麼。
當然這也要看題目難度,有些題目太難以至於擠出一個解法就花不少時間了。此時這步驟可能就會先省略,或是等第一個能動的版本(Working solution)寫完後面試官才會要你改進到更好的方案。
Do
排序那個做法的話,時間與空間複雜度是 foo,而用 Heap 那個解法的話則是 bar。他們各自的優點與缺點分別是 blablabla。因此,我會建議用解法 bla,你覺得如何?
Don't
排序很好寫,就用它吧!現在終於可以寫扣了吧?
寫程式
終於進入熟悉的寫扣環節,這個步驟就是考驗你平常寫程式的底子而已。除了整潔乾淨的程式碼以外,最重要的是隨時都要讓面試官知道你正在幹嘛!
我通常會邊寫邊講話,像是在教小孩子一樣講得清楚,這非常有助於面試官的理解。一般來說,面試官不怕你話太多,就怕你不講話。
另一個常見的問題是大家為了寫得快,常常用很短的無意義變數名(i, j, data, m, n…),這會大大降低程式碼的可讀性,使得面試官更難理解,你自己也容易寫錯,我已經看過無數次把 i, j 寫反的面試者了。就像工作一樣,建議盡量使用有意義的變數名(row, col, count…),讓你的程式碼像篇文章一樣很好讀,不需要太多額外的註解。
Do
現在寫的這個迴圈目的是為了 blabla,而那個變數是為了記錄 blabla。
Don't
(一聲不吭瘋狂打字,卡住的話停頓並沈默思考。面試官只能尷尬地看著你,想辦法讀心。)
主動檢查與測試
程式碼寫完後一定要自己主動檢查並測試!因為寫的時候常常會有點緊張而容易有些小問題,寫完稍微冷靜後再看一次是可以輕易地發現的。在我眼中,如果面試者能不需提醒而自己發現並修正錯誤的話,這通常不會扣分反而加分。
想像你同事寫了一堆扣後完全沒測,直接丟過來讓你 Review 結果被你抓出一堆很基本的問題,你對這個同事的印象也不會太好吧?
Do
我先用這個測資來試看看,當輸入是 abc 時,這行會變成 foo 然後下一行會算出 bar,就可以 blablabla,最後證明是正確的。這樣測試後我相信這個程式碼沒有問題,你來看看吧?
Don't
寫完啦!我相信這是對的,你來看看吧?
複雜度分析
如果上面忘記提的話,這就是你最後的機會來展現分析時間與空間複雜度的能力。如果你不主動說,面試官也一定會問,那當然是主動點好。
Do
同(3)。
Don't
(寫完了我真棒)扣已經寫完了,有下一題嗎?
延伸問題
面試題的設計常常是有延伸問題的,因為這樣可以省下解釋新問題的時間。它可能是同個問題但不同解法,也可能是原先的問題加上了新條件。當你題目做完時,如果時間充裕,面試官就會問延伸題。通常如果你感覺題目過於簡單,那八成是因為還有延伸題等著你。
如果碰上了,就請重複以上步驟,加油!如果有在步驟三好好分析的話,此時你說不定會發現當時提出的各種方案之中,有些解法是可以直接套用。
像這例題的一種延伸就是從有限的 N 個數字變成無限輸入的數字串,並要求你找出任意輸入長度時的第 K 大的數字。這時排序就不可能了,只剩 Heap 變成最佳解。
打完收工
面試結束時,通常會是人資或最後一輪的面試官護送你離開公司。這時會輕鬆許多,可以簡單聊聊甚至喇賽。
我面試完臉書時(《Facebook 總部面試心得分享與免費冰淇淋》),就是面試官送我走的。他很熱心問我離開前想幹嘛?我就說剛剛看到冰淇淋🍦攤位,想吃!他就帶我去那裡排隊拿冰淇淋,搜刮了些飲料後再送我離開。排隊時也很友善地聊聊我當前的工作,以及給了他的公司信箱,若我需要的話他可以幫忙催進度。雖然後來沒用上,但這態度很加分。
而我在面試第一份工作時,面試結束時人資(也是台灣人)很親切問我要不要一起吃晚餐,然後在晚餐時就直接提早告訴我面試結果了。當時的閒聊也讓我跟這位人資變得很熟,即使離開公司後也一直有在保持聯絡。
剩下的就是等待面試結果了,祝順利呀!