研發(fā)筆試卷復(fù)盤:基礎(chǔ)考點(diǎn)與方法論)
前幾天整理舊硬盤翻出一個(gè)命名為“筆試整理”的文件夾里面靜靜躺著一份2015年人人網(wǎng)研發(fā)筆試卷E的掃描版。說(shuō)實(shí)話看到它的第一反應(yīng)是懷念第二反應(yīng)是“這玩意兒現(xiàn)在還有人看嗎”。但當(dāng)我真的一張一張重新過(guò)完后發(fā)現(xiàn)一個(gè)挺有意思的事實(shí)這套卷子里的考點(diǎn)和出題思路放到今天依然有很強(qiáng)的參考價(jià)值。不是說(shuō)要你去背原題而是它代表了一類典型的、以“基礎(chǔ)扎實(shí)度”為核心考察目標(biāo)的研發(fā)筆試題。如果你正在準(zhǔn)備校招或者工作幾年后想回來(lái)補(bǔ)一補(bǔ)底層的短板花點(diǎn)時(shí)間復(fù)現(xiàn)這套卷子的考查邏輯比盲目刷幾十道LeetCode更能幫你建立知識(shí)體系。很多人拿到一套舊卷子容易走兩個(gè)極端要么覺(jué)得過(guò)時(shí)了沒(méi)價(jià)值要么試圖在網(wǎng)上找答案背下來(lái)。我都不推薦。更務(wù)實(shí)的做法是把試卷當(dāng)成一份“考點(diǎn)清單”逐題拆解它到底在考察什么然后對(duì)照自己的知識(shí)樹查漏補(bǔ)缺。這篇博文我也不會(huì)去逐題貼答案——網(wǎng)上找不到完整版而且意義不大——而是把這套卷子里的核心題型、答題思路、踩坑點(diǎn)整理成一套可以復(fù)用的方法論。無(wú)論你考不考人人網(wǎng)這套方法都能遷移到其他公司的研發(fā)筆試?yán)铩?. 為什么2015年這套題到現(xiàn)在還有復(fù)盤價(jià)值1.1 一套試卷的時(shí)代背景基礎(chǔ)能力永遠(yuǎn)在考察名單上人人網(wǎng)在2015年正處于移動(dòng)端轉(zhuǎn)型的關(guān)鍵期后端技術(shù)棧從傳統(tǒng)的LAMP架構(gòu)向分布式方向演進(jìn)。這份研發(fā)筆試卷E的題型構(gòu)成其實(shí)非常典型地反映了那個(gè)階段互聯(lián)網(wǎng)公司對(duì)研發(fā)崗位的期待你不僅要會(huì)用框架還得懂底層原理你不僅要能寫業(yè)務(wù)代碼還得能處理高并發(fā)、大數(shù)據(jù)量下的性能問(wèn)題。具體到試卷結(jié)構(gòu)大致是五個(gè)板塊選擇題、填空題、簡(jiǎn)答題、編程題、設(shè)計(jì)題。選擇題主要覆蓋數(shù)據(jù)結(jié)構(gòu)、C/Java語(yǔ)法細(xì)節(jié)、操作系統(tǒng)、網(wǎng)絡(luò)協(xié)議填空題則偏重于輸出結(jié)果題比如給一段代碼讓你寫運(yùn)行結(jié)果考察的是對(duì)語(yǔ)言機(jī)制的理解深度簡(jiǎn)答題通常會(huì)問(wèn)“進(jìn)程和線程的區(qū)別”“TCP三次握手為什么是三次”這類經(jīng)典問(wèn)題編程題一般是兩道左右鏈表和動(dòng)態(tài)規(guī)劃是常客設(shè)計(jì)題壓軸往往是一道系統(tǒng)設(shè)計(jì)或方案設(shè)計(jì)。這套結(jié)構(gòu)放在今天依然不過(guò)時(shí)。你去看現(xiàn)在各大廠的筆試卷子除了多了些機(jī)器學(xué)習(xí)、云原生的題目之外底層考察邏輯幾乎沒(méi)變。原因很簡(jiǎn)單基礎(chǔ)知識(shí)是面試官唯一能快速判斷你“潛力”的指標(biāo)。項(xiàng)目經(jīng)驗(yàn)可以包裝但操作系統(tǒng)、網(wǎng)絡(luò)、數(shù)據(jù)結(jié)構(gòu)這些硬知識(shí)問(wèn)幾句就能看出真實(shí)水平。1.2 這套卷子考察的三個(gè)核心維度復(fù)盤完整份卷子我總結(jié)出它想考察的三個(gè)核心維度這三個(gè)維度也是所有研發(fā)筆試的通用標(biāo)尺。第一個(gè)維度是“編碼基本功”。包括語(yǔ)法細(xì)節(jié)是否扎實(shí)、邊界條件是否考慮周全、代碼風(fēng)格是否整潔。比如C的虛函數(shù)機(jī)制、構(gòu)造析構(gòu)順序、指針與引用的區(qū)別這類題目如果平時(shí)只是“用過(guò)”而沒(méi)有“思考過(guò)”很容易翻車。第二個(gè)維度是“算法思維”。不是看你會(huì)不會(huì)背題而是看你在限定時(shí)間內(nèi)能否從暴力解推進(jìn)到最優(yōu)解并正確分析復(fù)雜度。第三個(gè)維度是“系統(tǒng)視野”。簡(jiǎn)答題和設(shè)計(jì)題考察的是綜合能力比如緩存的一致性、分布式鎖的實(shí)現(xiàn)、數(shù)據(jù)庫(kù)索引的選擇。能答好這類題目的人通常不是靠刷題刷出來(lái)的而是真的寫過(guò)、踩過(guò)坑、總結(jié)過(guò)。所以復(fù)盤這套卷子的關(guān)鍵不在于“記住正確答案”而在于“理解考察者為什么這么問(wèn)”。一旦想通了這一點(diǎn)你就擁有了出題人視角以后再遇到新題也不會(huì)慌。2. 算法與數(shù)據(jù)結(jié)構(gòu)題拿滿分的答題節(jié)奏2.1 鏈表和樹的基礎(chǔ)題先從手寫邊界條件說(shuō)起這套試卷的編程題里鏈表相關(guān)題目幾乎從不缺席。原因有兩點(diǎn)第一鏈表能考察指針操作的基本功第二鏈表的邊界條件多很容易暴露“眼高手低”的問(wèn)題。我印象中這類題的經(jīng)典考法是“判斷鏈表是否有環(huán)”和“反轉(zhuǎn)鏈表”。如果你覺(jué)得這兩道題簡(jiǎn)單不妨問(wèn)自己三個(gè)問(wèn)題。第一個(gè)問(wèn)題快慢指針判斷鏈表有環(huán)快指針每次走兩步而不是三步為什么很多人答不上來(lái)。其實(shí)核心原因是兩步可以保證慢指針進(jìn)入環(huán)后在一圈內(nèi)必然被快指針追上。如果走三步追上可能需要多圈雖然最終也能判斷但邊界分析就復(fù)雜得多。第二個(gè)問(wèn)題反轉(zhuǎn)鏈表時(shí)如果要求不能用遞歸迭代寫法里需要幾個(gè)指針答案是三個(gè)prev、cur、next。少一個(gè)就會(huì)斷鏈。第三個(gè)問(wèn)題鏈表的入環(huán)節(jié)點(diǎn)怎么找這涉及Floyd判圈算法的擴(kuò)展——快慢指針相遇后一個(gè)指針從頭出發(fā)一個(gè)指針從相遇點(diǎn)出發(fā)每次各走一步再次相遇的位置就是入環(huán)點(diǎn)。樹的考察點(diǎn)則集中在遍歷上。層序遍歷看起來(lái)簡(jiǎn)單但很多人的寫法有隱患用nullptr作為層分隔符當(dāng)節(jié)點(diǎn)值本身就可能是空指針時(shí)容易出錯(cuò)。更好的做法是每次記錄當(dāng)前隊(duì)列的大小然后一次性處理完這一層這樣既不需要額外標(biāo)記也不容易出錯(cuò)。前序、中序、后序的遞歸版本大家都熟但要求你寫非遞歸版本時(shí)就需要用棧手動(dòng)模擬這里經(jīng)常有人卡住。2.2 動(dòng)態(tài)規(guī)劃的套路從暴力遞歸到狀態(tài)壓縮動(dòng)態(tài)規(guī)劃是每年筆試的壓軸常客這套卷子也不例外。遇到動(dòng)態(tài)規(guī)劃題我推薦的標(biāo)準(zhǔn)步驟是先寫暴力遞歸再改成記憶化搜索最后再優(yōu)化成遞推。不要一上來(lái)就追求最優(yōu)解那樣反而容易卡殼。舉個(gè)例子最長(zhǎng)不重復(fù)子串這道題。暴力做法是枚舉所有子串檢查是否有重復(fù)字符復(fù)雜度O(n^2)。這能幫你厘清問(wèn)題模型確保思路正確。接著用滑動(dòng)窗口優(yōu)化維護(hù)一個(gè)窗口右指針不斷右移如果遇到重復(fù)字符左指針就跳到上次出現(xiàn)位置的下一位。這時(shí)復(fù)雜度降為O(n)并且不需要額外數(shù)組來(lái)標(biāo)記字符是否出現(xiàn)過(guò)只需要一個(gè)長(zhǎng)度為128或256的數(shù)組記錄每個(gè)字符上次出現(xiàn)的位置。還有一個(gè)高頻考點(diǎn)是背包類問(wèn)題。0-1背包的遞推公式大部分人能寫出來(lái)但問(wèn)到“如何優(yōu)化成一維數(shù)組”時(shí)容易忽略內(nèi)層循環(huán)必須倒序。為什么因?yàn)橐痪S數(shù)組滾動(dòng)更新時(shí)正序會(huì)讓同一個(gè)物品被重復(fù)使用而0-1背包每個(gè)物品只能用一次所以必須倒序。這個(gè)細(xì)節(jié)也是面試官最愛(ài)挖的坑。2.3 字符串處理的邊界陷阱字符串題看似簡(jiǎn)單實(shí)際是失分重災(zāi)區(qū)。這套卷子的字符串題大多圍繞“子串”“子序列”“反轉(zhuǎn)”這幾個(gè)關(guān)鍵詞展開(kāi)。比如“反轉(zhuǎn)字符串中的單詞順序”要求原地操作。很多人能寫出整體反轉(zhuǎn)再局部反轉(zhuǎn)的思路但漏掉了兩個(gè)關(guān)鍵邊界單詞間可能有多個(gè)空格輸入字符串首尾可能有空格。C里用istringstream可以省事但筆試環(huán)境不一定允許你依賴這些庫(kù)函數(shù)的語(yǔ)義Java里用split( )會(huì)丟掉連續(xù)空格需要手動(dòng)處理。最穩(wěn)妥的寫法是先去除首尾空格再用雙指針從后往前逐詞提取。再比如判斷兩個(gè)字符串是否為變位詞。常規(guī)解法是用哈希表統(tǒng)計(jì)字符頻率這沒(méi)錯(cuò)。但如果你能用長(zhǎng)度為26的數(shù)組代替哈希表代碼會(huì)更簡(jiǎn)潔而且面試時(shí)能體現(xiàn)你對(duì)“有限字符集”的敏感度。2.4 代碼風(fēng)格是隱形評(píng)分項(xiàng)這一點(diǎn)很多人會(huì)忽略筆試的編程題通常是人工閱卷代碼風(fēng)格直接影響印象分。好的代碼風(fēng)格包括變量命名有意義而不是a、b、c關(guān)鍵步驟有注釋函數(shù)邊界檢查充分復(fù)雜度分析寫在代碼塊旁邊或注釋里。我見(jiàn)過(guò)不少人代碼邏輯全對(duì)但整個(gè)函數(shù)寫的密密麻麻沒(méi)有空行變量名全部是拼音縮寫閱卷人一眼就不想看。反過(guò)來(lái)一份結(jié)構(gòu)清晰、注釋得當(dāng)?shù)拇a即使有小bug閱卷人也更愿意相信你只是筆誤而不是不會(huì)。3. 語(yǔ)言基礎(chǔ)與計(jì)算機(jī)系統(tǒng)題送分題里的暗坑3.1 C/Java基礎(chǔ)容易被問(wèn)倒的三個(gè)點(diǎn)這套卷子的選擇題里C和Java的基礎(chǔ)題占了很大比例但很多“感覺(jué)會(huì)”的題實(shí)測(cè)一做就錯(cuò)。我挑三個(gè)最典型的點(diǎn)說(shuō)一下。第一個(gè)是C虛函數(shù)相關(guān)的機(jī)制。題目可能會(huì)問(wèn)你“構(gòu)造函數(shù)是否可以聲明為虛函數(shù)”“析構(gòu)函數(shù)為什么通常要聲明為虛函數(shù)”。前者是因?yàn)樘摵瘮?shù)表在構(gòu)造期間尚未完全建立調(diào)用虛函數(shù)會(huì)失去多態(tài)意義后者是因?yàn)橥ㄟ^(guò)基類指針刪除派生類對(duì)象時(shí)析構(gòu)函數(shù)不虛就無(wú)法正確調(diào)用派生類的析構(gòu)邏輯導(dǎo)致內(nèi)存泄漏。很多有幾年經(jīng)驗(yàn)的人第一反應(yīng)是“我平時(shí)不手動(dòng)管理內(nèi)存不關(guān)我事”但寫底層庫(kù)的人絕對(duì)躲不開(kāi)這個(gè)問(wèn)題。第二個(gè)是Java集合框架里的坑。比如HashMap的擴(kuò)容機(jī)制、ConcurrentHashMap為什么線程安全、ArrayList和LinkedList的區(qū)別為什么不能只看“查詢快慢”。很多人背過(guò)結(jié)論但被問(wèn)到“HashMap在JDK 1.7和1.8中擴(kuò)容有什么不同”時(shí)就露餡了。1.7是頭插法并發(fā)擴(kuò)容可能形成環(huán)1.8改成了尾插法并且在鏈表長(zhǎng)度超過(guò)8且數(shù)組長(zhǎng)度大于64時(shí)轉(zhuǎn)成紅黑樹。這些不是考題細(xì)節(jié)而是設(shè)計(jì)思想值得花時(shí)間真正理解。第三個(gè)是內(nèi)存管理。C的RAII、智能指針的引用計(jì)數(shù)機(jī)制Java的GC分代回收、Minor GC和Full GC觸發(fā)的條件。這些題看起來(lái)是概念題但背后關(guān)聯(lián)著JVM調(diào)優(yōu)、服務(wù)性能排查面試官問(wèn)出來(lái)其實(shí)是想知道你有沒(méi)有排查線上問(wèn)題的基礎(chǔ)。3.2 操作系統(tǒng)與網(wǎng)絡(luò)考點(diǎn)不能只背結(jié)論操作系統(tǒng)和網(wǎng)絡(luò)協(xié)議是筆試中“看似送分、實(shí)則暗坑”的重災(zāi)區(qū)因?yàn)轭}目經(jīng)常把結(jié)論包裝在具體場(chǎng)景里考。比如進(jìn)程與線程的區(qū)別老生常談。但換成“一個(gè)進(jìn)程內(nèi)多個(gè)線程共享哪些資源、獨(dú)占哪些資源”就有很多人說(shuō)不全。共享的是地址空間、文件描述符、信號(hào)處理器獨(dú)占的是棧和寄存器。再比如死鎖的四個(gè)必要條件很多人能背出來(lái)但題目給一個(gè)具體場(chǎng)景問(wèn)你“破壞的是哪個(gè)條件”就要費(fèi)一番思量了。網(wǎng)絡(luò)部分這道卷子幾乎必然出現(xiàn)TCP狀態(tài)圖。高頻題包括TIME_WAIT為什么是2MSL、為什么不能是1MSLSYN Flood的原理和防護(hù)HTTP和HTTPS的區(qū)別以及TLS握手過(guò)程。這里我建議不要死背狀態(tài)名而是把每個(gè)狀態(tài)背后的“為什么”想清楚。比如2MSL這個(gè)數(shù)字是因?yàn)橐WC最后一個(gè)ACK能重傳同時(shí)確保本次連接的所有報(bào)文在網(wǎng)絡(luò)中消失避免干擾新連接。理解了設(shè)計(jì)意圖任何變著花樣的題都繞不開(kāi)你。3.3 數(shù)據(jù)庫(kù)索引B樹是重點(diǎn)中的重點(diǎn)數(shù)據(jù)庫(kù)相關(guān)的題目在這套卷子里占了兩個(gè)方向一是SQL寫法二是索引原理。SQL寫法相對(duì)容易多表關(guān)聯(lián)、聚合函數(shù)、子查詢掌握基本語(yǔ)法就能應(yīng)付。索引原理才是真正拉分的地方。經(jīng)典問(wèn)題為什么索引選用B樹而不是B樹、紅黑樹或者哈希表標(biāo)準(zhǔn)答案講三點(diǎn)。第一點(diǎn)B樹的所有數(shù)據(jù)都在葉子節(jié)點(diǎn)葉子節(jié)點(diǎn)之間用指針連接非常適合范圍查詢和排序。第二點(diǎn)非葉子節(jié)點(diǎn)不存數(shù)據(jù)每層能容納更多索引鍵讓整棵樹更矮減少磁盤I/O次數(shù)。第三點(diǎn)紅黑樹是二叉搜索樹樹高太高不適合磁盤存儲(chǔ)。哈希索引雖然單點(diǎn)查詢是O(1)但完全無(wú)法支持范圍查詢。除了B樹還有一個(gè)面試官愛(ài)問(wèn)的細(xì)節(jié)復(fù)合索引的最左匹配原則。給一個(gè)復(fù)合索引(a, b, c)查詢條件WHERE a1 AND c3時(shí)能用到索引嗎答案是能用到a這一列但c用不到。原因是索引排序規(guī)則是先按a排再按b排再按c排跳過(guò)了b就沒(méi)有辦法用c來(lái)定位到精確區(qū)間。這類題做錯(cuò)的人非常多本質(zhì)原因是沒(méi)理解索引的底層排序結(jié)構(gòu)。4. 設(shè)計(jì)題和開(kāi)放題給面試官一條清晰的思考路徑4.1 系統(tǒng)設(shè)計(jì)題的回答框架這套試卷的壓軸設(shè)計(jì)題通常會(huì)給你一個(gè)具體場(chǎng)景比如“設(shè)計(jì)一個(gè)短URL系統(tǒng)”或“設(shè)計(jì)一個(gè)帶過(guò)期時(shí)間的緩存”。很多人一看到設(shè)計(jì)題就慌了因?yàn)槠綍r(shí)只寫業(yè)務(wù)代碼沒(méi)系統(tǒng)想過(guò)架構(gòu)。我總結(jié)了一個(gè)四步框架基本可以應(yīng)對(duì)80%的設(shè)計(jì)題。第一步是需求澄清。問(wèn)清楚是讀多寫多還是讀多寫少、預(yù)估QPS多少、數(shù)據(jù)量多大。筆試雖然沒(méi)法提問(wèn)但你可以在回答中先定義這些假設(shè)。第二步是容量估算。根據(jù)假設(shè)算一下QPS峰值、存儲(chǔ)空間、帶寬需求。這里不需要精確數(shù)量級(jí)對(duì)就行。第三步是核心鏈路設(shè)計(jì)。畫出來(lái)請(qǐng)求從客戶端到服務(wù)端經(jīng)過(guò)哪些組件每個(gè)組件的職責(zé)是什么。第四步是容錯(cuò)與擴(kuò)展。如果某個(gè)組件掛了怎么保證可用性如果需要擴(kuò)容怎么做水平擴(kuò)展。拿短URL系統(tǒng)舉例。核心問(wèn)題有兩個(gè)長(zhǎng)URL轉(zhuǎn)短URL的算法以及短URL跳轉(zhuǎn)長(zhǎng)URL的存儲(chǔ)方案。常見(jiàn)算法是發(fā)號(hào)器思想——用自增ID或雪花算法生成唯一ID再轉(zhuǎn)成62進(jìn)制字符串作為短URL后綴。也有人用哈希算法比如MD5取前8位但存在碰撞風(fēng)險(xiǎn)需要加鹽或布隆過(guò)濾器輔助。存儲(chǔ)層通常用KV數(shù)據(jù)庫(kù)Redis作為緩存加速M(fèi)ySQL做持久化。這些思路不需要你寫完整代碼但整個(gè)鏈路必須清晰。4.2 場(chǎng)景落地帶過(guò)期時(shí)間的本地緩存如果是設(shè)計(jì)一個(gè)本地緩存需要注意的點(diǎn)就更細(xì)了。首先是數(shù)據(jù)結(jié)構(gòu)的選擇。可以用HashMap加雙向鏈表實(shí)現(xiàn)LRU淘汰也可以直接用LinkedHashMap但要注意線程安全性。筆試時(shí)如果要求手寫通常不強(qiáng)制考慮并發(fā)但如果能提到“加鎖粒度、分段鎖、讀寫鎖”等優(yōu)化方案會(huì)加分不少。關(guān)于過(guò)期時(shí)間經(jīng)典實(shí)現(xiàn)是懶刪除加定期清理的組合。懶刪除就是在get的時(shí)候檢查過(guò)期時(shí)間過(guò)期了返回null并刪除定期清理則是啟動(dòng)一個(gè)后臺(tái)線程周期性掃描一部分key刪除過(guò)期數(shù)據(jù)。這兩種方式結(jié)合既保證了讀操作的實(shí)時(shí)性又能及時(shí)釋放內(nèi)存。4.3 設(shè)計(jì)題中的“溝通感”筆試怎么體現(xiàn)設(shè)計(jì)題和編程題不同沒(méi)有唯一的“標(biāo)準(zhǔn)答案”閱卷人更看重的是你的思考路徑是否完整。所以答題時(shí)不要把每個(gè)細(xì)節(jié)都鋪開(kāi)寫而是要有主次先給結(jié)論再給理由最后補(bǔ)充邊界情況。比如“緩存和數(shù)據(jù)庫(kù)怎么保證一致性”這種問(wèn)題很多人知道要“先更新數(shù)據(jù)庫(kù)再刪緩存”但不知道為什么要這樣。如果面試官追問(wèn)“刪緩存失敗怎么辦”你能提到消息隊(duì)列重試或者訂閱binlog異步刪除緩存就說(shuō)明你是真思考過(guò)而不是背了面經(jīng)。這種追問(wèn)式的細(xì)節(jié)才是閱卷人打高分的依據(jù)。5. 考后復(fù)盤一套卷子怎么榨出三套的價(jià)值5.1 錯(cuò)題歸因而不是對(duì)答案做完一套模擬卷最忌諱的就是簡(jiǎn)單對(duì)完答案就翻篇。我給自己定的規(guī)矩是每道錯(cuò)題必須寫出歸因——是“知識(shí)沒(méi)學(xué)”還是“學(xué)了沒(méi)記住”還是“記住但不會(huì)用”三種歸因?qū)?yīng)的補(bǔ)救措施完全不同。知識(shí)沒(méi)學(xué)就去補(bǔ)基礎(chǔ)找教材對(duì)應(yīng)章節(jié)重新過(guò)一遍。學(xué)了沒(méi)記住說(shuō)明缺少系統(tǒng)整理需要做知識(shí)點(diǎn)卡片或思維導(dǎo)圖。記住但不會(huì)用這是最遺憾的說(shuō)明刷題量不夠?qū)︻}型不敏感。你需要做的是找類似知識(shí)點(diǎn)的不同考法反復(fù)練習(xí)到形成條件反射。5.2 建立考點(diǎn)-題目映射表復(fù)盤這套2015年的試卷時(shí)我做了一個(gè)很簡(jiǎn)單卻很高效的表格推薦給你。表格有三列考點(diǎn)名稱、考察方式、我的掌握程度。比如“鏈表有環(huán)判斷”這一行考察方式是“快慢指針時(shí)間復(fù)雜度O(n)”掌握程度是“熟練”。再比如“B樹索引最左匹配”這一行考察方式是“寫SQL判斷是否走索引”掌握程度是“會(huì)用但說(shuō)不清原理”。這張表做完之后你的薄弱點(diǎn)一目了然。每天花20分鐘只看“掌握程度為不熟練”的行堅(jiān)持一周提升非常明顯。5.3 復(fù)盤后的模擬訓(xùn)練限時(shí)、手寫、不查資料復(fù)盤完之后一定要安排一次限時(shí)模擬。環(huán)境盡量貼近真實(shí)筆試白紙手寫不進(jìn)IDE不查函數(shù)文檔完全靠記憶。時(shí)間分配上選擇和填空控制在30分鐘內(nèi)簡(jiǎn)答和設(shè)計(jì)題40分鐘編程題50分鐘最后留一點(diǎn)時(shí)間檢查。手寫這件事真的很重要。在IDE里你可能靠補(bǔ)全提示和編譯器報(bào)錯(cuò)發(fā)現(xiàn)代碼問(wèn)題但筆試題沒(méi)有這個(gè)條件。手寫一遍能逼你重新記憶類名、方法簽名和語(yǔ)法細(xì)節(jié)。我當(dāng)年手寫ArrayList的擴(kuò)容邏輯時(shí)才發(fā)現(xiàn)自己居然記不清數(shù)組拷貝時(shí)System.arraycopy的參數(shù)順序這種細(xì)節(jié)在IDE里永遠(yuǎn)不會(huì)暴露但考場(chǎng)上一定會(huì)失分。最后再分享一個(gè)小技巧。復(fù)盤一套題不要只看自己錯(cuò)在哪還要想想這道題是怎么被設(shè)計(jì)出來(lái)的。既然問(wèn)了“為什么快指針走兩步”面試官就能從你的回答里聽(tīng)出你是“用過(guò)算法”還是“理解算法”。帶著出題人視角去學(xué)習(xí)從“背答案的人”變成“懂原理的人”這才是這套老試卷能帶給你的最大增量。