【轉自一畝三分田】談談面試官在面試coding題目時的考察終點與心理活動html
本人簡介: 曾經微軟dev, 35+, 10年經驗, 有FLG offer. 去年加入一個start up 公司, 最近前景不明, 在猶豫要不要去個穩定點的大公司。 我從sde開始面試其餘人, 到如今估計面試過100+人次的面試和debrief。 我面過coding, problem solving, design, behavior. 本帖子只談論純粹coding, 視狀況討論要不要再開帖子討論其餘方面。
本文涉及下面幾個問題:
1) 我刷過這個題目, 還要不要假裝
2) 我以爲這題很簡單, 可是不知道爲何就掛了
3) 我以爲面試官不是很友好, 沒提示
4) 我必定要bug free才能被錄取嗎
5) leet code的hard問題真的會被問到嗎? 考起來有什麼意義?
咱們從一個很是經典的, 你們可能都刷過的題目開始。 序列化/反序列化 二叉樹。先說個背景, 能面到我這裏的, 基本須要面試者有3-5年的面試經驗。 作爲應聘任何微軟或者flg的高級dev (63 and above, T4/E4 and above), 面試官其實都是假設你刷過很多題目的。 我假設你刷過這個題目, 因此我並不關心你寫的到底有多快,寫的是否是徹底bug free, 我更關心的是你作事的方式和溝通問題的能力。 具體請看下面。
1. 提出問題, 請序列化/反序列化二叉樹。
什麼? 面試者不知道什麼是序列化, 反序列化? 那我就問個多線程爬蟲, timing LRU 一類的。 若是多線程, 鎖也不會, 那說明這個面試者的項目經驗很不足。 爲了和其餘有經驗的人相match, 每每我會給一個很open的問題, 或者一個很難的hard coding (取決於他已經被考察了哪一個方面). 我我的以爲不多有面試官上來會考你 very hard coding question, 只是當某個面試者與其餘面試人比顯得至關缺乏項目經驗, 那他除非能在聰明敏捷或者下苦功方面有突出表現, 不然很難擊敗其餘候選人。
2. 交流階段
若是面試者立刻開始寫程序, 或者立刻給出他的想法, 我會以爲面試者太過於着急了。 在實際項目中, 你很熟悉的地方可能成爲項目中的滑鐵盧, 由於你熟悉的地方可能有變化, 可能有個big change你不知道, 可能很快你熟悉的api就不工做了。 你老是要有很好的溝通能力, 確保你們知道你在作什麼, 及早的發現你的錯誤。 在code review甚至是test 階段被人發現問題對項目來講就是個災難。
我指望面試者可以在這個階段提出一些問題, 例如,有什麼限制條件嗎? 二叉樹的value是什麼類型? 這個api誰來使用, 內部的仍是public的? 這個api更注重speed仍是space? 我須要多線程嗎? 若是面試者沒問任何問題立刻開始照着leetcode的signature開始coding, 甚至class 名字也叫solution(不少人), 我會以爲面試者作事的方式不夠成熟。 可能之後工做中會很毛躁, 須要人來指導。
3. 不管你提出的建議是什麼, 例如你說你以爲speed更重要, 我可能會說我更期待space. 這樣作是避免陷入你最熟悉的套路。 假設我說, 我更須要序列化以後的空間佔用最小。 這時候通常的候選人不會刷到這麼深, 開始思考。
若是候選人根本沒有辦法優化空間, 那我會認爲他give up too early. 我但願候選人能安靜的思考, 提出幾種方案, 哪怕方案不成立。
若是候選人提出過多的方案, 沒有問help, 這些方案也不工做, 我就認爲候選人溝通有問題, 沒法把握好度。
舉個leetcode的例子來講明問題的深刻, leetcode的序列化格式中, ','是必要的嗎? ‘[’是必要的嗎? 有沒有辦法用byte直接序列化? byte還能變長嗎? base64是什麼? zip會有幫助嗎?
4. 候選人選定方案後, 我但願他能和我溝通, 看看是否是在有限時間內可以寫完。 項目中, 不少時候誰都知道什麼design是正確的, 什麼是bad smell, 最聰明的人不是能作出最好design的, 而是在有限時間內能給出你們都能接受的solution的人。 若是空間優化很是好, 可是代碼將超級複雜, 沒法寫完, 那麼面試者應該及時和我交流。 我也會偶爾提醒一下這樣能不能在40分鐘內寫完。 若是面試者堅持, 我不會堅持, 我會看他是否是能寫完。 這就是either strong hire or fail.
5. 候選人可能這時候說太複雜了, 咱們簡化一下, 簡化到他熟悉的, 刷過的coding.
6. coding 開始
到這一步, 若是你作了2,3,4,5中的大部分, 而且code看起來彷佛是work的, 沒有什麼致命的問題,我不會糾結於好比正負數, nullpointer, int.min, coding是否是整潔一類的無聊問題。 通常就開始7. 若是你2,3,4,5都skip, 那麼通常我就但願你bug free, 不然你沒辦法和其餘候選者作比較。每每bug free又要求你code組織很好, 不然誰都很難一眼看出你有沒有問題。
7. follow up
還有什麼能改進的嗎? 這是考察面試者的知識面, 也看你是否是耐心。 不少時候, 不少面試者作出題目高興的忘乎所以, 到這裏就開始語無倫次的亂說, 這不會影響到是否是hire, 可是可能會影響是否是strong hire, 也可能影響到你的level.
舉例子: 我以爲還須要寫點java doc啊,unit test, regression test, performance tuning, benchmarking, A/B testing, 等等。
總結: 若是你能想到1-7中的全部點, 誰會在意你是否是刷過這個題目? 即便你刷過這個題目, 我也十分肯定你刷的比別人好不少, 你就是我心中想要的那個同事。 反之, 若是你只作到了6#, 可是別人作了1,2,3,4,5,6,7, 那你又怎麼能面試成功呢?java
前幾天寫了個關於面試官心理活動和側重點的帖子, 見 談談面試官在面試coding題目時的考察終點與心理活動, 求大米, 首先感謝你們的捧場與大米, 也請你們原諒個人一些錯別字與語無倫次(爲了快速求大米寫的粗糙了一點), 反應超出個人預期。 也讓我有了動力接着寫這一篇帖子。
在上一篇帖子中提到了coding的通常步驟與考察點, 在開貼討論design,behavior, culture fit前, 繼續深刻的討論一下coding的考察範圍, 也以此作爲對一些同窗, 特別是new grad的問題的統一回復。我就不排版和檢查拼寫了, 你們繼續湊合讀。
coding 種類與應對策略
大體上, 面試官在開始面試前, 會收到一封email, 裏面回大體說明每一個人須要側重於考察面試者的哪一個方面。 對於coding來講, 通常有三類問題, 每一個面試官會被分配到一類問題。
1. solid coding
這類問題說白了, 誰都知道怎麼作, 純粹就是考察coding是否是紮實, 平時本身寫code多很少, 能不能快速的把本身的idea轉化爲code。 對於面試者來講屬於必考種類, new grad 通常會有兩輪甚至三輪這樣的題目, 有不少工做經驗的人可能就只有1輪了。 這類題目不過關, 極可能電面死掉或者前幾輪忽然死亡。
solid coding又通常能夠分紅兩個小類:
1.1 考察你對算法的基本理解以及邊界條件的運用, 好比findkth largest integer, search in rotate array, bit manipulation 等等。
1.2 考察你對基本數據結構以及複雜度的理解。 好比binary search tree, linkedlist vs array, stack, tree dfs, tree bfs 等等。
按難度來分, easy的好比3 sum, tree level order iterator. medium 難度的好比 reverse linked list from index m to index n, course schedule,string multiplication, hard 難度的好比valid number, 複雜的calculator等。
應對策略:
1.1 類型, 若是是簡單和medium的沒得說了, 就是但願你又快又好, 除了勤奮和熟練, 沒有什麼好策略。 對於像merge sort, partition這類的算法, 若是7-8分鐘還寫不出bug free我估計就沒戲了。easy問題請多多注意邊界條件, int 溢出, nullpointer, 負數, 非法輸入等。
hard 1.1的請參考1.3
1.2 類型, 簡單和medium請在寫代碼前多闡明覆雜度, 這類數據結構的問題每每也能夠在coding前畫圖來表示運行狀態, 圖畫的清楚也是個重要的加分項。 hard請參考1.3
1.3 hard類型的coding題目. 這每每是考察你的solid coding的能力, 即我在前文中提到的, 你作事的方式和你思考問題的方法。 即給你一個coding任務, 你如何從白板開始, 一步步的作出bug free的程序。 這類問題的過程重於結果。 好比valid number, 你能確保每實現一個模塊, 都沒有regressgion, 都沒有bug, 比你一會兒實現全部的feature可是有不少bug 要好不少。 通常來講面試官看你是否可以一步步的分隔出小的coding模塊(method), 你如何設計test case, 你如何可以確保這些test case能cover全部的scenario, 你是否是和麪試官提早作了足夠的溝通而且限定了coding範圍。 從這個角度來講, valid number實際上是個很不錯的solid coding面試題。 限於篇幅, 我就不展開來講了。
2. problem resolving
這類問題對於new grad是關鍵, 也是能幫你differentiate的關鍵。 說白了, 計算機並非只有算法,咱們還須要數據庫, 操做系統, 網絡, 安全等方面的知識。 new grad這些方面要弱一些, 因此面試者但願new grad能展示出思惟敏捷, 多思考, 快速反應的能力。 problem resolving就爲了考察這個能力而誕生的。
problem resolving也能夠分紅四個小類型。
2.1 API design. 這類問題是爲了更深刻的考察你對數據結構的理解與運用。 例如LRU cache, insert delete getRandom ALL O(1) , design twitter等等。
2.2 Abstraction. 這類問題是考察你能不能把一個相對抽象的問題規約到你熟悉的問題上面。 好比skyline problem, int stream find median, cleaning robot等等。
2.3 計算機小程序, 例如thread pool, 爬蟲,日誌merge等, random generator等。
2.4 dynamic programming問題。 這類問題有點像solid problem resolving. 主要考察你是否是有systemmatic的方法來下降一個brute force程序的複雜度
這類問題通常都不是很easy的問題, 根據面試官心情, 可能走的很深很難。 也可能最後演變成bar raiser.
應對策略:
2.1 主要考察你對數據結構的深層次認識。 首先請同時確保你理解了題目的意思, 最好能問清點條件 例如immutable array max subarray sum, 那數組未來會變嗎?問清這類的問題有助於你寫代碼前作好重構和測試的準備。 其次, 若是你能證實你選擇的算法的複雜度, 甚至證實這就是最佳複雜度, 那是一個大大的加分項, 若是不能, 至少你也問問面試官是否是已經滿意了再開始寫代碼。
2.2 這個我本身也頭疼, 說實話若是第一次碰見了skyline, 我也不知道能不能搞定。 你們有好辦法請回復有什麼好辦法能系統化的解決這類的問題, 我我的以爲不少時候靠靈光一閃。
2.3 這類問題主要看你平時積累, 也是一大類不能經過leetcode練習的問題。臨時抱佛腳的話, 我我的推薦java concurrency in practice這本書。
2.4 動態規劃, 我不知道爲何不少人懼怕動態規劃。 面試中的動態規劃大體分爲單向遞歸(首或者尾), O(n2)或者O(n3) 距離遞歸, O(mn)遞歸,有限定條件的NP (揹包)。 每種類型聽幾節課, 懂了基本原理便可。 至於貪心和帶狀態的dp(走道鋪磚)一類的dp, 至少我沒在面試中遇到過, 由於很難臨時造出一道這樣的題目, 面試官通常也沒這個能力和時間來思考題目是否是嚴謹。 貪心準備下加油站, 迪傑斯特拉, 最小生成樹就足夠了。
3. bar raiser
這類的問題只有當onsite應聘者的數量遠遠大於head count的時候, 或者你前幾輪明顯超出了電面時對你的定位纔會發生。 其目的是幫助公司選擇最優秀的人。 對應聘者來講, 壞消息是要度過痛苦一小時, 好消息是你能充分了解這公司厲害的人有多厲害, 能充分展現你的能力, 甚至被越級錄取也不是不可能。
bar raiser也是三小類。 c++
較難的hard題,最好在完全理解答案的基礎上背題。面試官比較看重的是獲得這個解法的過程。
咱們來以skyline的表演爲例,拋磚引玉一下~
題目要求的是建築的剪影,能夠抽象爲每一個固定橫座標上的最高點(劃重點:提取問題核心)。所以這個解法能夠分紅兩部分:
(1)如何把input轉換爲線性,從而抽象成掃描線問題(甩名詞:sweep line)
(2)掃描線的具體實現
第一部分,若是想要簡單掃一遍,數據必須是按x軸排序的。假設咱們 start_x 來對 building 排序,則end_x仍然是無序的,這樣很差。(此時演技爆棚一拍腦殼想到)咱們只須要知道skyline的線段是在哪裏開始的,所以在building高度發生變化的X位置進行處理便可。building的開始和結束都算是高度變化,所以能夠把 start 和 end 拆開處理,只須要標記 X 位置上的高度數據以及這個高度是開始仍是結束。
至於每一個X位置數據的具體結構,能夠用一個tuple(int h 高度,bool start 表示是開始仍是結束),也能夠像高票解法同樣用正數表明開始、負數表明結束。能夠和麪試官闡明。
第二部分,主要是如何維持一個高度的queue。
闡明在掃描過程當中須要三個操做,插入(遇到start),刪除(遇到end),獲取最大值(高度更新),所以可能有:
1. 由於要取最大值嘛,因此很明顯咱們試試heap,插入O(logn),max O(1),可是刪除是O(n),不太好,咱們試試別的;
2. balanced bst (c++ ordered map以及java treemap),全場O(logn),統統O(logn);
3. 有沒有可能優化方法1呢?能夠用 hashmap + heap的方式來實現,O(logn) insert, O(logn) remove, O(1) get_max。
第一部分稍微舉例說明了一下如何展現思路。
第二部分我認爲是裝逼重點。能寫方法3,就先列出1和2,指出他們的不足,而後提出3。若是懶得實現3,先提出1,再提出2,指出紅黑樹的時間優於heap,在面試官看來也是對數據結構足夠熟練的應用了。
最後記得提出edge case,好比兩個building高度相同怎麼辦(僞裝思考一下)若是先push start,再pop end,就不會有高度變化的問題了嘛,因此咱們重寫compare函數的時候注意一下就好了。
以上整個過程,在表演不崩的狀況下用5-8分鐘來解釋,我認爲都是能夠的。
兩年沒刷題了,具體細節可能記得不太清楚。最近剛開始當面試官,在演技方面給你們舉個栗子🌰。對於這種candidate,即便對方多是在表演,若是可以把問題肢解得這麼清楚、把多種實現細節的trade-off分析得這麼明白,我也會給一個pass的。
(皮完就跑 #滑稽#
補充內容 (2018-7-29 05:14):
解釋思路的時間擴展到10+分鐘應該也能夠吧,諸位要不要試試mock一下計個時?咱們統計一下(笑)
總之只要思路連貫,有理有據使人信服,就不會演崩。但必定要有develop思路的過程,這也能體現對解法的充分理解git
寫一點刷題感想github
前先後後刷題也一年了,不少感想。因此想總結出來。我也不知道本身說的對不對,因此正好和你們交流,相互學習。
最核心的三條:
1. 想刷的好沒別的,惟手熟爾。
刷題跟高考數學本質如出一轍。想一想過去高中三年啥事兒都不作,每天作卷子,看到題就大概知道怎麼作。而現在由於生活忙碌,各類事情distraction,致使刷題可能變得時間不夠。再看看leetcode contest那些20分鐘作完四道題的牛人,不少都是有ACM競賽背景的。固然或許他們的確天資過人,但我更相信他們是從小開始訓練coding,見多識廣,經驗豐富,submission上萬遍,付出無數努力才能維持如此高的應試水平的。
另外,對於全部leetcode mediun題甚至一些hard題,也是要求你在半個小時甚至更短期內作出來,不是要你花幾個月幾年時間作調研寫報告或者作research探究人類未知,因此內容自己應該是很簡潔的一個小問題(固然簡潔不表明簡單)。因此刷不出來?why?就一句話:刷少了。知識點不夠熟,或者XX算法沒見過,或者這種題型很陌生。不會的東西均可以在網上找到答案/資料/訓練,而不像作research你面對的是unknown的東西須要花費巨大精力去不斷嘗試和研究;因此不會的就學習,缺乏的就補課,每學一點,就進步一點。很是公平。
因此主要仍是本身努力的不夠。這是我最大的感覺。
2. 最好作到不間斷。
上面說的是刷題本質,回答的是what的問題。如今說一下how的問題。
個人一個感想就是,從應試記憶的角度來講,必定要不間斷的刷題,時刻保持手感。中間若是停掉一個月或者幾個月,再pickup起來的成本就會很大。這也是我本身的一個重大教訓,我本身毅力不夠。每每別的事情一忙碌,就完全把刷題拋在腦後了。過了一個月再回來狂刷。但我慢慢發現這個方式並很差,那些刷題很牛的人,他們必定是細水長流的,天天刷,哪怕天天只submit一次也能夠。
固然說的容易,作起來難。就是毅力。
3. 不停的總結套路+題型。。
若是說刷題有啥技巧,最核心的我以爲就是要不停的總結套路和題型。固然還沒刷到200題的就不要care這個,先把量作到足夠多才有必要總結。仍是那個古老的規律:好記性不如爛筆頭。以前說了,刷題本質就是努力,而努力的核心就是不停刷;如何高效的不停刷呢?就是作總結筆記。並且必定是參考其餘人筆記後,作出的最適合本身的那個筆記,宛如本身的指紋,全世界獨一份屬於你的。好比,DFS/BFS畫個圖寫個pseudo code總結下。而後有的題爲啥BFS比DFS強?拿一個題作例子總結一下。有的題是DFS/BFS+union find;有的題是DFS/BFS+DP,分別總結下。backtracking裏各類subset,permutation,combination總結一下看看他們的區別。Comparator怎麼寫?忘記了?趕忙總結個模板。相似的,2D array/priorityqueue如何sort? 。。。
無論任何大模板,仍是小細節,都要作筆記。無論你用evernote,github,gitbook仍是什麼別的。
除了少數技巧特殊的題目,其餘全部題目必定掌握核心靈魂,而不是死記硬背。我過去就犯過這種錯誤。已經兩個月沒刷題了,忽然來個面試,慌了,因此趕忙把code背一背寄但願碰到原題。最後面試的時候一塌糊塗。而我那時候尚未很認真的作總結。因此有一份刷題總結在手,做爲面試前複習的精華,就不怕任何突如其來的面試了。
因此刷來刷去,刷出來的就是套路。如何掌握這些套路?努力唄。
另外還兩小點。
第一就是我以爲如今題型核心就是DFS/BFS/Tree/Backtracking/UF以及延伸出的一些東西,這些都是一條繩上的螞蚱(說的不對請指正)。固然還有一個點就是DP。 可是過於難的DP實在是想不出來。因此我不知道DP這個東西也是能夠經過不停努力掌握的嗎?
第二就是,面試的時候和leetcode刷題仍是很不一樣的。lc刷習慣了會產生對那種環境的依賴感。而實際面試可能要你本身寫main function;或者白板面試。這些都是要額外訓練的。面試