研發(fā)筆試題深度拆解:核心考點(diǎn)與復(fù)習(xí)方法論)
1. 筆試背后的出題邏輯美團(tuán)當(dāng)年在考什么老讀者都知道我每年都會(huì)翻出幾套大廠早年真題做深度拆解。一方面是因?yàn)榻?jīng)典題目永遠(yuǎn)不會(huì)過(guò)時(shí)另一方面是這些題背后藏著出題團(tuán)隊(duì)對(duì)工程師能力的真實(shí)定義。今天要聊的這套美團(tuán)2016研發(fā)工程師筆試題二我前前后后帶過(guò)好幾屆學(xué)弟學(xué)妹刷它每次都有新收獲。先給沒(méi)趕上那波校招的朋友交代下背景。2016年是移動(dòng)互聯(lián)網(wǎng)大戰(zhàn)正酣的時(shí)候美團(tuán)和大眾點(diǎn)評(píng)剛剛完成合并業(yè)務(wù)線急速擴(kuò)張研發(fā)崗位需求量巨大。那年的筆試題放在今天來(lái)看難度不算變態(tài)但覆蓋面相當(dāng)廣而且非常強(qiáng)調(diào)基礎(chǔ)功。整套題分為客觀題和主觀編程題兩大部分客觀題涵蓋數(shù)據(jù)結(jié)構(gòu)、算法、操作系統(tǒng)、網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)主觀題則是經(jīng)典的算法編程題要求現(xiàn)場(chǎng)手寫(xiě)代碼。這套題最值得研究的地方不在于某道題有多難而在于它非常典型地反映了大廠研發(fā)崗筆試的出題思路不考偏題怪題就用基礎(chǔ)知識(shí)點(diǎn)組合出題考察你在有限時(shí)間內(nèi)能不能快速定位考點(diǎn)、寫(xiě)出干凈代碼。為什么說(shuō)它適合拿來(lái)練手因?yàn)?016年的題目難度曲線比現(xiàn)在友好不少?zèng)]有太多冷門(mén)偏門(mén)的智力題大多數(shù)題目都是“跳一跳夠得著”的水平。對(duì)于準(zhǔn)備校招、社招沖刺期的朋友來(lái)說(shuō)這類真題是最佳的模擬訓(xùn)練素材。而對(duì)于已經(jīng)工作幾年的開(kāi)發(fā)者重新做一遍這套題也能檢驗(yàn)自己的基礎(chǔ)有沒(méi)有退化。我當(dāng)年第一次拿到這套題的時(shí)候其實(shí)也沒(méi)能全部做對(duì)。但正是那些做錯(cuò)的題讓我發(fā)現(xiàn)了自己在操作系統(tǒng)和網(wǎng)絡(luò)協(xié)議上的知識(shí)盲區(qū)。所以這篇文章不只是把題目過(guò)一遍更重要的是和你聊聊每道題背后在考什么、解題的切入點(diǎn)在哪里、有什么容易踩的坑。1.1 為什么每一道題背后都有崗位畫(huà)像很多同學(xué)刷題容易陷入一個(gè)誤區(qū)就是只管“這道題怎么做”不管“出題人為什么這么出”。但你一旦站在出題人的角度去想會(huì)發(fā)現(xiàn)每一道題都有它的用意。美團(tuán)2016年這套筆試題我拆解完之后最大的感受是它想招的不是“刷題機(jī)器”而是**“基礎(chǔ)扎實(shí)、思路清晰、代碼規(guī)范”**的工程師。舉個(gè)例子客觀題里關(guān)于進(jìn)程和線程的題目表面上是在考概念辨析實(shí)際上是在考察你有沒(méi)有真正理解并發(fā)編程的本質(zhì)。因?yàn)楹蠖搜邪l(fā)每天都要和線程池、鎖、異步任務(wù)打交道如果連進(jìn)程和線程的底層差異都講不清楚上線出問(wèn)題的時(shí)候根本無(wú)從排查。再比如數(shù)據(jù)結(jié)構(gòu)里的樹(shù)相關(guān)題目考的是二叉樹(shù)遍歷、重建、平衡調(diào)整等基礎(chǔ)操作。這些知識(shí)點(diǎn)看起來(lái)老掉牙但凡是涉及到搜索、索引、緩存淘汰策略底層都是這些基礎(chǔ)結(jié)構(gòu)的變體。出題人希望通過(guò)筆試篩選出那些真正理解數(shù)據(jù)結(jié)構(gòu)本質(zhì)而不是只會(huì)調(diào)API的候選人。所以你在復(fù)習(xí)這套題的時(shí)候不能只背答案。我建議你每做完一道題都問(wèn)自己三個(gè)問(wèn)題這道題考察的是哪個(gè)核心知識(shí)點(diǎn)如果我是面試官我會(huì)在下一輪追問(wèn)什么這個(gè)知識(shí)點(diǎn)在我真實(shí)項(xiàng)目中有沒(méi)有用到過(guò)帶著這三個(gè)問(wèn)題去刷題效率會(huì)比盲目刷三遍高得多。1.2 研發(fā)崗筆試的??寄K與權(quán)重根據(jù)我對(duì)美團(tuán)歷年真題的觀察研發(fā)工程師筆試的知識(shí)點(diǎn)分布基本遵循一個(gè)“二八定律”。那我來(lái)梳理一下2016年這套題二涉及的模塊以及它們的權(quán)重關(guān)系考察模塊大致占比典型考察形式復(fù)習(xí)優(yōu)先級(jí)數(shù)據(jù)結(jié)構(gòu)與算法40%-50%選擇題編程題極高操作系統(tǒng)15%-20%選擇題高計(jì)算機(jī)網(wǎng)絡(luò)10%-15%選擇題高數(shù)據(jù)庫(kù)10%左右選擇題中高Java/C基礎(chǔ)10%左右選擇題中邏輯與智力題5%以下選擇題低從這個(gè)分布能看出兩個(gè)關(guān)鍵信息。第一算法和數(shù)據(jù)結(jié)構(gòu)是絕對(duì)的大頭拿下這部分基本就拿下了半張卷子。第二操作系統(tǒng)和網(wǎng)絡(luò)是區(qū)分度最高的模塊因?yàn)楹芏嗤瑢W(xué)在學(xué)校里這兩門(mén)課學(xué)得比較水工作之后又很少系統(tǒng)復(fù)習(xí)容易丟分。我當(dāng)時(shí)復(fù)習(xí)的時(shí)候給自己定的策略是**算法題保證能AC兩道以上選擇題里的操作系統(tǒng)和網(wǎng)絡(luò)題盡量全對(duì)數(shù)據(jù)庫(kù)和Java基礎(chǔ)靠刷題鞏固手感。**這個(gè)策略執(zhí)行下來(lái)效果不錯(cuò)因?yàn)樗惴}大家都會(huì)準(zhǔn)備拉不開(kāi)差距反而是那些看起來(lái)“簡(jiǎn)單”的基礎(chǔ)知識(shí)題才是真正拉開(kāi)分差的地方。1.3 這類題目拿到手先定策略筆試和平時(shí)刷題最大的區(qū)別是有時(shí)間限制。美團(tuán)2016年這套題我記得是100分鐘左右完成所有題目。時(shí)間緊、題量大如果沒(méi)有一個(gè)明確的答題策略很容易在前面卡住導(dǎo)致后面的大題沒(méi)時(shí)間做。我個(gè)人的經(jīng)驗(yàn)是拿到卷子先花3-5分鐘快速瀏覽所有題目按“會(huì)做-可能做出來(lái)-完全不會(huì)”給題目分類。先做會(huì)做的再攻克可能做出來(lái)的最后蒙完全不會(huì)的。選擇題不要空著因?yàn)楣P試通常不倒扣分蒙一個(gè)還有四分之一的概率拿分。編程題的建議是先看題目描述快速判斷考察的是哪類算法貪心、動(dòng)態(tài)規(guī)劃、二分、DFS/BFS等然后先在草稿紙上寫(xiě)偽代碼確認(rèn)思路沒(méi)問(wèn)題再動(dòng)手寫(xiě)實(shí)現(xiàn)。很多同學(xué)一上來(lái)就敲代碼寫(xiě)到一半發(fā)現(xiàn)思路錯(cuò)了浪費(fèi)大量時(shí)間。我在帶新人刷題的時(shí)候一直強(qiáng)調(diào)筆試考的不只是你會(huì)不會(huì)更是你在有限時(shí)間內(nèi)的決策能力。2. 核心知識(shí)點(diǎn)拆解從真題倒推復(fù)習(xí)重點(diǎn)接下來(lái)我們進(jìn)入正題把這套題涉及的核心知識(shí)點(diǎn)一個(gè)一個(gè)拆開(kāi)來(lái)看。我不會(huì)把整套題從頭到尾念一遍答案那樣對(duì)讀者的幫助非常有限。我會(huì)挑出最重要的、最具代表性的知識(shí)點(diǎn)講清楚“它是什么、為什么考、怎么掌握”。2.1 數(shù)據(jù)結(jié)構(gòu)與算法筆試的定海神針數(shù)據(jù)結(jié)構(gòu)與算法在研發(fā)崗筆試中的地位就像語(yǔ)文數(shù)學(xué)在高考中的地位一樣。這套二的題目里算法相關(guān)的內(nèi)容覆蓋了數(shù)組、鏈表、棧、隊(duì)列、樹(shù)、圖、排序、查找、動(dòng)態(tài)規(guī)劃、貪心等多個(gè)方向。先說(shuō)一個(gè)很多人的誤區(qū)以為算法題做得越多越好。其實(shí)不然關(guān)鍵是有沒(méi)有形成自己的解題方法論。比如看到“求最大/最小值”“求最優(yōu)解”要能立刻聯(lián)想到動(dòng)態(tài)規(guī)劃或貪心看到“找第K大”“Top K問(wèn)題”要能想到堆排序或快速選擇算法看到“連通性”“最短路徑”要能鎖定并查集或Dijkstra。以樹(shù)這塊為例。當(dāng)年筆試?yán)飿?shù)相關(guān)的題目很經(jīng)典比如給出一棵二叉樹(shù)的前序遍歷和中序遍歷結(jié)果要求重建這棵二叉樹(shù)。這個(gè)題解題的關(guān)鍵在于理解三種遍歷方式的性質(zhì)前序遍歷的第一個(gè)節(jié)點(diǎn)是根節(jié)點(diǎn)中序遍歷中根節(jié)點(diǎn)左邊是左子樹(shù)、右邊是右子樹(shù)。通過(guò)遞歸不斷縮小范圍就能重建整棵樹(shù)。如果你要把這類題目做熟練我建議你準(zhǔn)備一個(gè)代碼模板庫(kù)把常見(jiàn)的算法模板整理成自己能默寫(xiě)的程度。比如二叉樹(shù)的前中后序遍歷遞歸和非遞歸版本二分查找的各種變體查找第一個(gè)等于、最后一個(gè)等于、第一個(gè)大于等快速排序和歸并排序的模板動(dòng)態(tài)規(guī)劃的“狀態(tài)定義-轉(zhuǎn)移方程-初始化-遍歷順序”四步法單例模式、工廠模式等??荚O(shè)計(jì)模式我當(dāng)年自己的做法是把每個(gè)模板用A5紙打印出來(lái)夾在文件夾里每天隨機(jī)抽三張默寫(xiě)。堅(jiān)持一個(gè)月之后筆試遇到基礎(chǔ)算法題基本不用過(guò)腦子手比腦子快。2.2 操作系統(tǒng)和網(wǎng)絡(luò)的經(jīng)典考點(diǎn)操作系統(tǒng)和計(jì)算機(jī)網(wǎng)絡(luò)這兩門(mén)課是科班出身和半路轉(zhuǎn)行的程序員差距最明顯的地方。2016年這套筆試題里操作系統(tǒng)部分考察了進(jìn)程與線程的區(qū)別、死鎖產(chǎn)生的條件、虛擬內(nèi)存與頁(yè)面置換算法、進(jìn)程調(diào)度策略等網(wǎng)絡(luò)部分則考了TCP三次握手、TCP與UDP的區(qū)別、HTTP協(xié)議狀態(tài)碼、DNS解析過(guò)程等。這些考點(diǎn)到今天依然是面試高頻題因?yàn)樗鼈兪撬泻蠖碎_(kāi)發(fā)的地基。比如TCP三次握手看似簡(jiǎn)單但你能把這個(gè)過(guò)程講深講透嗎為什么是三次而不是兩次為什么連接時(shí)是三次握手?jǐn)嚅_(kāi)時(shí)卻是四次揮手如果SYN包丟了怎么辦這些追問(wèn)連環(huán)炮一樣砸過(guò)來(lái)光靠記住“三次握手交換了幾個(gè)包”是遠(yuǎn)遠(yuǎn)不夠的。在學(xué)習(xí)這些知識(shí)點(diǎn)的時(shí)候我特別推薦“給同伴講一遍”的方法。我當(dāng)年是這樣操作的每周找一個(gè)晚上把本周學(xué)的一個(gè)操作系統(tǒng)或網(wǎng)絡(luò)知識(shí)點(diǎn)用白板給室友講一遍講到對(duì)方能聽(tīng)懂為止。如果講著講著發(fā)現(xiàn)卡殼了那就是自己理解還沒(méi)到位回去再查資料重新理解。這個(gè)方法比做100道題都管用因?yàn)椤拜敵觥睍?huì)倒逼“輸入”。2.3 數(shù)據(jù)庫(kù)與Java基礎(chǔ)后端研發(fā)的硬門(mén)檻數(shù)據(jù)庫(kù)相關(guān)的題目雖然占比不算最高但只要出現(xiàn)基本就是送分題。2016年這套題里涉及的數(shù)據(jù)庫(kù)知識(shí)點(diǎn)包括MySQL的索引結(jié)構(gòu)B樹(shù)、事務(wù)的ACID特性、SQL語(yǔ)句的執(zhí)行順序、表連接的區(qū)別等。其中的關(guān)鍵是理解為什么MySQL選擇B樹(shù)作為索引的數(shù)據(jù)結(jié)構(gòu)而不是二叉樹(shù)或者哈希表。這個(gè)問(wèn)題的答案其實(shí)充分展現(xiàn)了數(shù)據(jù)結(jié)構(gòu)在真實(shí)工程中的價(jià)值B樹(shù)的非葉子節(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù)只在葉子節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù)并且葉子節(jié)點(diǎn)之間有指針相連這樣可以充分利用磁盤(pán)的預(yù)讀特性減少IO次數(shù)。而二叉樹(shù)的樹(shù)高太高哈希表又無(wú)法支持范圍查詢。能把這個(gè)邏輯講清楚說(shuō)明你是真的理解了索引的本質(zhì)而不是死記硬背。Java基礎(chǔ)方面考察的點(diǎn)集中在集合類源碼、多線程、異常處理、JVM內(nèi)存模型等。很多同學(xué)覺(jué)得這些知識(shí)點(diǎn)瑣碎、記不住其實(shí)是缺少一個(gè)主線。比如學(xué)習(xí)JVM內(nèi)存模型可以以“一個(gè)Java對(duì)象從創(chuàng)建到回收的全過(guò)程”為主線把堆、棧、方法區(qū)、垃圾回收算法、分代回收策略串起來(lái)。有了主線知識(shí)點(diǎn)就不再是孤立的而是一張網(wǎng)。3. 編程題實(shí)操一道典型題目的完整解題流程說(shuō)完了基礎(chǔ)知識(shí)我們來(lái)點(diǎn)硬核的。我挑了一道具有代表性的編程題完整走一遍從審題到提交的實(shí)操流程。這道題的原型是2016年美團(tuán)筆試二里的一道題目我用近似描述來(lái)還原重點(diǎn)在解題思路和代碼實(shí)現(xiàn)。3.1 題目原型與思路分析題目描述還原版給定一個(gè)整數(shù)數(shù)組請(qǐng)找出其中兩個(gè)數(shù)使得它們的和等于一個(gè)給定的目標(biāo)值。返回這兩個(gè)數(shù)在數(shù)組中的下標(biāo)。題目看起來(lái)很簡(jiǎn)單對(duì)吧但作為筆試編程題它考察的遠(yuǎn)不止“能寫(xiě)出來(lái)”這么簡(jiǎn)單。面試官和考官看重的是你的解法時(shí)間復(fù)雜度是多少空間復(fù)雜度是多少能不能處理邊界情況代碼是否規(guī)范我們來(lái)分析幾種思路暴力解法兩層for循環(huán)遍歷所有數(shù)對(duì)時(shí)間復(fù)雜度O(n2)空間復(fù)雜度O(1)。優(yōu)點(diǎn)是代碼極其簡(jiǎn)單但放到筆試場(chǎng)景里n稍大一點(diǎn)就會(huì)超時(shí)基本拿不到滿分。排序雙指針先對(duì)數(shù)組排序然后用左右指針從兩端向中間移動(dòng)。時(shí)間復(fù)雜度O(nlogn)空間復(fù)雜度O(1)忽略排序開(kāi)銷。這個(gè)解法思路巧妙但要注意排序會(huì)讓數(shù)組下標(biāo)信息丟失需要額外記錄原始下標(biāo)。哈希表法遍歷數(shù)組對(duì)于每個(gè)數(shù)x檢查target-x是否已經(jīng)在哈希表中。時(shí)間復(fù)雜度O(n)空間復(fù)雜度O(n)。這是最推薦的解法因?yàn)榇a簡(jiǎn)潔、效率高、思路清晰。從筆試拿分角度來(lái)說(shuō)我會(huì)優(yōu)先寫(xiě)哈希表法因?yàn)樗鼤r(shí)間最優(yōu)而且不容易出錯(cuò)。如果你能額外提一句“如果要求空間復(fù)雜度為O(1)可以改成排序雙指針”那會(huì)顯得思考周全有加分效果。3.2 代碼實(shí)現(xiàn)與復(fù)雜度優(yōu)化哈希表法的Java實(shí)現(xiàn)如下import java.util.HashMap; import java.util.Map; public class TwoSum { public int[] twoSum(int[] nums, int target) { MapInteger, Integer map new HashMap(); for (int i 0; i nums.length; i) { int complement target - nums[i]; if (map.containsKey(complement)) { return new int[]{map.get(complement), i}; } map.put(nums[i], i); } return new int[]{-1, -1}; } }這段代碼的核心思路是邊遍歷邊存而不是先把所有元素存進(jìn)哈希表再遍歷。為什么要這么做因?yàn)檫@樣可以避免“同一個(gè)元素被使用兩次”的問(wèn)題。舉個(gè)例子數(shù)組是[3, 3]目標(biāo)是6如果先把兩個(gè)3都存進(jìn)哈希表再遍歷時(shí)會(huì)發(fā)現(xiàn)map.containsKey(3)為true但你能確定這個(gè)3不是當(dāng)前這個(gè)3自己?jiǎn)嵊谩斑叡闅v邊存”的方式判斷的時(shí)候當(dāng)前元素還沒(méi)有被放入哈希表所以不會(huì)出現(xiàn)自己配自己的問(wèn)題。關(guān)于復(fù)雜度就更直觀了每個(gè)元素最多被訪問(wèn)兩次一次查表一次存表時(shí)間復(fù)雜度是O(n)。哈希表存儲(chǔ)最多n個(gè)元素空間復(fù)雜度是O(n)。在實(shí)際筆試中這種時(shí)空權(quán)衡通常是被允許的因?yàn)轭}目限制一般不會(huì)苛刻到要求O(1)空間。3.3 邊界條件和測(cè)試用例設(shè)計(jì)寫(xiě)代碼只寫(xiě)主流程是不夠的筆試閱卷時(shí)一定會(huì)看你的代碼能否處理邊界情況。我整理了一下這道題需要注意的邊界條件數(shù)組長(zhǎng)度為0或者為1不可能有兩個(gè)數(shù)應(yīng)該返回空結(jié)果或者異常數(shù)組中包含負(fù)數(shù)哈希表法天然支持負(fù)數(shù)但暴力法要注意判斷條件目標(biāo)值可能是負(fù)數(shù)或0同樣影響不大但如果你使用了預(yù)設(shè)默認(rèn)值比如用0初始化可能會(huì)出錯(cuò)存在多個(gè)解題目通常要求返回任意一個(gè)解即可但如果你返回的是第一個(gè)解要確保遍歷順序正確沒(méi)有解的情況要有返回值約定比如返回[-1, -1]或者拋出異常針對(duì)以上邊界條件筆試前最好養(yǎng)成一個(gè)習(xí)慣寫(xiě)完代碼后花2分鐘手動(dòng)在草稿紙上跑一組測(cè)試用例。我一般會(huì)選三組普通情況、包含負(fù)數(shù)的情況、無(wú)解的情況。跑完確認(rèn)無(wú)誤后再提交能大大降低低級(jí)錯(cuò)誤的概率。這道題雖然簡(jiǎn)單但它是一個(gè)非常好的“模板題”。把這道題的解題流程圖刻在腦子里以后遇到類似的“數(shù)組中找目標(biāo)值”“判斷是否存在重復(fù)元素”“找出只出現(xiàn)一次的元素”等問(wèn)題都可以快速套用哈希表的思路。4. 筆試現(xiàn)場(chǎng)的時(shí)間管理與實(shí)戰(zhàn)避坑我在前面反復(fù)提到時(shí)間管理和答題策略這里專門(mén)展開(kāi)聊一聊。因?yàn)楦鶕?jù)我?guī)н^(guò)的學(xué)生反饋很多人在筆試中不是輸在知識(shí)儲(chǔ)備上而是輸在策略和心態(tài)上。4.1 拿到卷子先干什么這個(gè)“先干什么”直接決定你整場(chǎng)筆試的節(jié)奏。我建議按以下順序操作第一步快速瀏覽全部題目標(biāo)記難度。選擇題一般20-30道編程題一般2-3道?;?分鐘時(shí)間把所有題目掃一遍在心里給每道題打個(gè)難度標(biāo)簽“秒殺題”“思考題”“放棄題”。第二步先做秒殺題。什么叫秒殺題就是你一看到題目就知道考點(diǎn)是什么甚至不需要在草稿紙上演算就能給出答案的題。這類題要先做掉因?yàn)樗鼈兪悄阕钣邪盐漳玫降姆謹(jǐn)?shù)。而且先做會(huì)做的題能快速建立信心讓大腦進(jìn)入狀態(tài)。焦慮和恐慌是筆試最大的敵人而自信是消除恐慌最好的方法。第三步攻克思考題。這些題需要花時(shí)間推演可能要用到草稿紙列一下關(guān)系式或者在腦海中模擬一下數(shù)據(jù)結(jié)構(gòu)和算法的執(zhí)行過(guò)程。做這部分題的時(shí)候要注意時(shí)間盒我一般給自己設(shè)定每道題最多10分鐘10分鐘還沒(méi)有思路就先跳過(guò)等所有會(huì)做的題都做完了再回頭啃。第四步對(duì)于完全不會(huì)的題選擇題可以蒙一個(gè)答案編程題至少要寫(xiě)一個(gè)暴力解法能拿部分分就拿部分分。筆試閱卷是按點(diǎn)給分的一個(gè)能運(yùn)行的暴力解往往能拿到20%-30%的分?jǐn)?shù)比空著強(qiáng)太多了。4.2 選擇題的做題技巧選擇題雖然看起來(lái)簡(jiǎn)單但其實(shí)是最容易丟分的地方。因?yàn)榇髲S筆試的選擇題通常是不定項(xiàng)選擇多選、少選、錯(cuò)選都不得分。這就意味著你不僅要選對(duì)還要選全。應(yīng)對(duì)不定項(xiàng)選擇我總結(jié)了一個(gè)“先判斷正誤再判斷全誤”的方法。每道題先看選項(xiàng)中有沒(méi)有明顯的錯(cuò)誤項(xiàng)排除掉之后剩下的選項(xiàng)要逐一判斷是否完全正確。如果某句話里帶有“一定”“必須”“全部”“都”這類絕對(duì)化的詞匯大概率是錯(cuò)誤選項(xiàng)因?yàn)楣こ填I(lǐng)域很少有絕對(duì)的表述。還有一個(gè)小技巧是遇到不會(huì)的題目不要孤立地看它而是要結(jié)合它上下前后題目的知識(shí)點(diǎn)分布來(lái)推測(cè)。如果前面連著幾道都是數(shù)據(jù)結(jié)構(gòu)的題這道題突然考網(wǎng)絡(luò)協(xié)議那出題人可能是在考察你對(duì)知識(shí)體系的橫向聯(lián)系能力。這種題一般不會(huì)特別偏核心考點(diǎn)永遠(yuǎn)在??挤秶鷥?nèi)。4.3 編程題常見(jiàn)失分點(diǎn)我從閱卷人和被閱卷人的雙重角度整理了幾個(gè)編程題最常踩的坑不寫(xiě)異常處理。比如輸入?yún)?shù)為null或者數(shù)組長(zhǎng)度不合法代碼直接空指針異常。筆試環(huán)境里這會(huì)導(dǎo)致整道題判0分。變量命名隨意。用a、b、c作為變量名閱卷人很難看懂你的思路。我建議筆試中也要保持代碼規(guī)范使用有意義的變量名比如index、temp、current等。沒(méi)有注釋。程序核心邏輯處加一兩行注釋能幫助閱卷人快速理解你的思路。尤其當(dāng)你的代碼不是最優(yōu)解時(shí)注釋能告訴閱卷人“我是有思考的只是時(shí)間有限”。只寫(xiě)核心函數(shù)不寫(xiě)輔助判斷。比如題目要求處理非法輸入但是你只寫(xiě)了主邏輯沒(méi)有寫(xiě)輸入合法性校驗(yàn)。很多同學(xué)以為這是加分項(xiàng)其實(shí)這是基本要求。不分析復(fù)雜度。有些筆試系統(tǒng)會(huì)要求你填寫(xiě)時(shí)間和空間復(fù)雜度即使不強(qiáng)制填寫(xiě)我也建議在代碼注釋里寫(xiě)上。這能體現(xiàn)你的工程素養(yǎng)。說(shuō)到工程素養(yǎng)我多說(shuō)一句。很多應(yīng)屆生在筆試中容易忽視代碼的健壯性覺(jué)得只要“對(duì)給定輸入能運(yùn)行出正確結(jié)果”就行了。但在真實(shí)開(kāi)發(fā)中你寫(xiě)的代碼面對(duì)的輸入永遠(yuǎn)比你想象的復(fù)雜。所以筆試中養(yǎng)成嚴(yán)謹(jǐn)?shù)牧?xí)慣不僅是為了拿分更是為你以后的職業(yè)生涯打基礎(chǔ)。5. 從筆試到面試這道題的延伸價(jià)值很多人把筆試和面試當(dāng)作兩件獨(dú)立的事情來(lái)準(zhǔn)備其實(shí)這是一個(gè)巨大的誤區(qū)。大廠的招聘流程雖然分為筆試、技術(shù)面試、HR面試等多個(gè)環(huán)節(jié)但考察的核心能力是一致的。筆試中暴露出來(lái)的問(wèn)題如果不解決幾乎一定會(huì)在面試中再次被考察。5.1 筆試過(guò)后的復(fù)盤(pán)方法筆試結(jié)束后不管自我感覺(jué)好不好我強(qiáng)烈建議你花幾個(gè)小時(shí)做一次系統(tǒng)復(fù)盤(pán)。復(fù)盤(pán)不是把錯(cuò)題抄一遍就完了而是要分析錯(cuò)誤原因歸類整理。我常用的復(fù)盤(pán)表格如下題號(hào)知識(shí)點(diǎn)錯(cuò)誤類型錯(cuò)誤原因改進(jìn)措施第3題二叉樹(shù)遍歷思路錯(cuò)誤對(duì)中序遍歷性質(zhì)理解不透徹重新學(xué)習(xí)二叉樹(shù)三種遍歷的遞歸/非遞歸實(shí)現(xiàn)第8題TCP狀態(tài)知識(shí)盲區(qū)TIME_WAIT狀態(tài)的作用記混了畫(huà)TCP狀態(tài)機(jī)圖死記并理解編程題2動(dòng)態(tài)規(guī)劃狀態(tài)定義模糊沒(méi)有想清楚dp數(shù)組的含義整理動(dòng)態(tài)規(guī)劃解題模板每天練1題這個(gè)表格看起來(lái)簡(jiǎn)單但真的堅(jiān)持做下去你會(huì)在兩周之后發(fā)現(xiàn)自己對(duì)知識(shí)體系的掌握程度有了質(zhì)的飛躍。因?yàn)閺?fù)盤(pán)的目的是找到知識(shí)盲區(qū)而不是自我感動(dòng)式的努力。5.2 這類題目對(duì)現(xiàn)在的開(kāi)發(fā)者還有參考價(jià)值嗎每次分析早年真題都會(huì)有人問(wèn)現(xiàn)在都2025年了這些老題還有參考價(jià)值嗎我的答案是非常值得做但要帶著新舊對(duì)照的眼光去做。技術(shù)棧會(huì)更新?lián)Q代但底層思維不會(huì)。2016年的筆試題可能沒(méi)有以Dubbo、Spring Cloud、Redis Cluster為代表的分布式微服務(wù)題目但它考察的Java集合類、JVM內(nèi)存模型、MySQL索引原理、TCP/IP協(xié)議棧恰恰是理解這些新技術(shù)的基礎(chǔ)設(shè)施。如果你連B樹(shù)索引都搞不清楚怎么去理解分庫(kù)分表策略如果你連進(jìn)程和線程的區(qū)別都說(shuō)不明白怎么去分析線上服務(wù)CPU飆高的問(wèn)題而且我對(duì)比了近兩年美團(tuán)和其他大廠的筆試題發(fā)現(xiàn)算法部分的考察重點(diǎn)數(shù)組、鏈表、樹(shù)、動(dòng)態(tài)規(guī)劃、貪心幾乎沒(méi)有變化變的只是題目包裝方式。所以把2016年的真題吃透對(duì)于應(yīng)對(duì)當(dāng)前的筆試依然有很強(qiáng)的實(shí)戰(zhàn)意義。我個(gè)人的做法是每半年會(huì)拿一套早年真題當(dāng)“體檢”來(lái)做看看自己有沒(méi)有在繁忙的業(yè)務(wù)開(kāi)發(fā)中把基礎(chǔ)丟掉。這就像資深醫(yī)生定期做基礎(chǔ)檢查一樣看似簡(jiǎn)單但非常重要。6. 實(shí)操總結(jié)從這套題中提煉的復(fù)習(xí)方法論如果你看完上面的內(nèi)容還想知道一個(gè)更加濃縮的、可以直接上手的復(fù)習(xí)方案那我把這些年帶學(xué)員、自己做題的經(jīng)驗(yàn)再提煉成一套可執(zhí)行的方法論。這套方法論不僅適用于備考美團(tuán)也適用于大部分互聯(lián)網(wǎng)公司的研發(fā)崗筆試。6.1 為期四周的筆試沖刺計(jì)劃很多同學(xué)準(zhǔn)備筆試的時(shí)間其實(shí)只有一個(gè)月左右那這四周的時(shí)間怎么分配就非常重要了。第一周打基礎(chǔ)。把數(shù)據(jù)結(jié)構(gòu)、算法、操作系統(tǒng)、網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)的基礎(chǔ)知識(shí)快速過(guò)一遍重點(diǎn)是建立知識(shí)框架。推薦使用思維導(dǎo)圖工具把每個(gè)章節(jié)的知識(shí)點(diǎn)梳理成樹(shù)狀結(jié)構(gòu)每個(gè)知識(shí)點(diǎn)下面標(biāo)注核心概念和常見(jiàn)考點(diǎn)。第二周刷真題。集中刷5-10套大廠真題每次刷完都要做復(fù)盤(pán)。這一周的目標(biāo)是適應(yīng)考試節(jié)奏了解題量和難度找到自己的薄弱環(huán)節(jié)。第三周專項(xiàng)突破。根據(jù)復(fù)盤(pán)結(jié)果針對(duì)薄弱知識(shí)點(diǎn)進(jìn)行專項(xiàng)練習(xí)。比如動(dòng)態(tài)規(guī)劃弱就集中刷50道動(dòng)態(tài)規(guī)劃題目網(wǎng)絡(luò)協(xié)議弱就把TCP/UDP/HTTP相關(guān)的知識(shí)點(diǎn)系統(tǒng)過(guò)一遍并配合習(xí)題鞏固。第四周模擬沖刺。找完整的時(shí)間段模擬真實(shí)筆試環(huán)境做3-5套完整的模擬題。注意要嚴(yán)格按照考試時(shí)間限制中途不能翻書(shū)、不能上網(wǎng)查資料。模擬結(jié)束之后認(rèn)真復(fù)盤(pán)調(diào)整答題策略。6.2 最終的建議復(fù)習(xí)了大半年刷了幾百道題參加了幾場(chǎng)筆試面試之后回過(guò)頭來(lái)看這套2016年的美團(tuán)研發(fā)工程師筆試題二我的體會(huì)是真正讓你通過(guò)筆試的不是某一道題做得有多完美而是你在整個(gè)備考過(guò)程中建立起來(lái)的知識(shí)體系、解題直覺(jué)和從容心態(tài)。這套題只是一個(gè)載體它背后承載的是一套完整的知識(shí)框架和思維方式。你能從這個(gè)載體中吸收多少養(yǎng)分取決于你是把它當(dāng)作“任務(wù)”去完成還是當(dāng)作“地圖”去探索。最后分享一個(gè)我自己的小習(xí)慣每當(dāng)學(xué)完一個(gè)章節(jié)我都會(huì)在筆記本上寫(xiě)一段“如果我是面試官我會(huì)怎么考這個(gè)知識(shí)點(diǎn)”的假設(shè)題目。這個(gè)方法讓我從被動(dòng)答題變成了主動(dòng)出題思考深度完全不同。有興趣的讀者可以試試說(shuō)不定你也能發(fā)現(xiàn)學(xué)習(xí)的另一層樂(lè)趣。