校招筆試全解析:從基礎(chǔ)考點(diǎn)到編程題實(shí)戰(zhàn)復(fù)盤)
那年秋招我在很長(zhǎng)一段時(shí)間里都在投客戶端開發(fā)方向的崗位。點(diǎn)我達(dá)2019屆校招這場(chǎng)筆試是我印象比較深的一次。倒不是說(shuō)題目有多偏多難而是它的考察范圍非常典型幾乎把客戶端開發(fā)校招筆試該覆蓋的考點(diǎn)都過(guò)了一遍兼具廣度和深度。如果你正準(zhǔn)備客戶端開發(fā)相關(guān)崗位的校招筆試這篇文章可以當(dāng)作一份復(fù)盤筆記來(lái)看我會(huì)把當(dāng)時(shí)這場(chǎng)筆試的題型分布、核心考點(diǎn)、易錯(cuò)點(diǎn)和編程題的解題思路都拆開講清楚也會(huì)聊一些在普通面經(jīng)里不太會(huì)寫到的臨場(chǎng)細(xì)節(jié)。先說(shuō)結(jié)論這類筆試整體難度屬于中上但真正拉開差距的往往不是最后那道壓軸算法題而是前面選擇題里那些“好像會(huì)、一選就錯(cuò)”的基礎(chǔ)概念?;A(chǔ)不牢后面編程題寫得再順手總分也可能被拖下去。1. 筆試題型拆解一份典型的客戶端開發(fā)筆試拿到手先看什么1.1 題型分布與分值結(jié)構(gòu)我參加的那場(chǎng)筆試是線上限時(shí)答題總共120分鐘題量不算小。整體分為三個(gè)部分客觀題單選多選、簡(jiǎn)答題、編程題。具體的分值分布大概是這樣的題型數(shù)量分值占比考察側(cè)重單選20題左右約30%數(shù)據(jù)結(jié)構(gòu)、操作系統(tǒng)、網(wǎng)絡(luò)、語(yǔ)言基礎(chǔ)多選10題左右約15%概念辨析、邊界條件、易混淆知識(shí)點(diǎn)簡(jiǎn)答2~3題約15%客戶端機(jī)制理解、方案設(shè)計(jì)編程2題約40%算法實(shí)現(xiàn)、代碼規(guī)范性、復(fù)雜度意識(shí)客觀題一共占了近一半的分?jǐn)?shù)這其實(shí)是非常常見的校招筆試結(jié)構(gòu)。很多準(zhǔn)備筆試的同學(xué)容易把精力全壓在編程題上進(jìn)了考場(chǎng)才發(fā)現(xiàn)前面那些選擇題做起來(lái)并不輕松——每個(gè)選項(xiàng)都在“對(duì)與不對(duì)”的邊緣反復(fù)橫跳特別是多選題少選漏選都拿不到分。建議拿到試卷后先快速瀏覽一遍所有題目對(duì)編程題的難度心里有個(gè)數(shù)然后倒過(guò)來(lái)從客觀題開始逐項(xiàng)推進(jìn)。不要一上來(lái)就死磕某道選擇題任何一道題超過(guò)三分鐘沒有明確思路先標(biāo)記跳過(guò)。1.2 為什么筆試要考這些內(nèi)容作為客戶端開發(fā)崗位的候選人你得先想清楚一個(gè)問(wèn)題公司為什么要在筆試環(huán)節(jié)考這些內(nèi)容點(diǎn)我達(dá)這類業(yè)務(wù)形態(tài)的公司核心產(chǎn)品是一個(gè)高頻使用的移動(dòng)應(yīng)用一端連著配送員一端連著商戶和用戶??蛻舳碎_發(fā)工程師要面對(duì)的遠(yuǎn)不只是“寫頁(yè)面”這件事——地圖定位的持續(xù)回調(diào)、訂單狀態(tài)的實(shí)時(shí)推送、弱網(wǎng)環(huán)境下的接口請(qǐng)求重試、長(zhǎng)列表的滑動(dòng)性能、App崩潰率的控制每一樣都是真實(shí)的線上問(wèn)題。所以筆試不會(huì)只考API怎么調(diào)用它會(huì)通過(guò)基礎(chǔ)題看你有沒有扎實(shí)的計(jì)算機(jī)功底通過(guò)客戶端機(jī)制題看你是不是真懂Android或iOS的底層運(yùn)行原理通過(guò)編程題看你能不能寫出健壯、高效、可維護(hù)的代碼。換句話說(shuō)筆試篩選的不只是“會(huì)寫代碼的人”而是“能在這個(gè)業(yè)務(wù)場(chǎng)景里把代碼寫穩(wěn)的人”。理解到這一層你在準(zhǔn)備筆試時(shí)的側(cè)重點(diǎn)就會(huì)不一樣單純刷LeetCode不夠還得把操作系統(tǒng)、網(wǎng)絡(luò)、客戶端機(jī)制這些“地基”補(bǔ)牢。2. 核心考點(diǎn)深度解析高頻知識(shí)點(diǎn)與出題意圖2.1 數(shù)據(jù)結(jié)構(gòu)與算法不只是刷題數(shù)量的問(wèn)題這部分是客觀題和編程題的重疊區(qū)。客觀題里考察的數(shù)據(jù)結(jié)構(gòu)知識(shí)點(diǎn)主要集中在數(shù)組和鏈表的操作復(fù)雜度對(duì)比、棧和隊(duì)列的應(yīng)用場(chǎng)景、二叉樹的遍歷方式、哈希表的沖突處理、排序算法的穩(wěn)定性和復(fù)雜度。其中“排序算法在不同場(chǎng)景下的選擇”是出現(xiàn)頻率非常高的考點(diǎn)。比如題目會(huì)給出一組近乎有序的數(shù)據(jù)問(wèn)你用哪種排序效率最高——這就是在考察插入排序?qū)跤行驍?shù)據(jù)集的適應(yīng)能力而不是讓你直接背快排的時(shí)間復(fù)雜度。只有真正理解每種排序的“數(shù)據(jù)敏感度”現(xiàn)場(chǎng)才能快速判斷。算法題的考察方向則集中在字符串處理、鏈表操作、二叉樹相關(guān)的遞歸、動(dòng)態(tài)規(guī)劃入門級(jí)問(wèn)題以及一些基于業(yè)務(wù)場(chǎng)景的模擬題。點(diǎn)我達(dá)的業(yè)務(wù)和LBS強(qiáng)相關(guān)所以筆試?yán)锍霈F(xiàn)過(guò)類似“計(jì)算兩個(gè)坐標(biāo)點(diǎn)之間的距離”“按照距離對(duì)一批點(diǎn)排序”這類題目。這類題本身不復(fù)雜但它提醒你準(zhǔn)備客戶端筆試時(shí)幾何計(jì)算和空間數(shù)據(jù)處理的基本思路要有一點(diǎn)概念這些知識(shí)在真實(shí)業(yè)務(wù)里很常用。字符串處理的題是校招筆試的常客幾乎不會(huì)缺席。常見的有字符串去重、字符統(tǒng)計(jì)、最長(zhǎng)公共前綴、反轉(zhuǎn)字符串等。這類題難度不大但非??简?yàn)編碼基本功邊界條件處理、空指針判斷、字符編碼的處理、時(shí)間復(fù)雜度的控制全是踩分點(diǎn)。我的建議是字符串相關(guān)的題型不要只看解題思路一定要自己手寫一遍完整代碼因?yàn)檫@類題最容易出現(xiàn)“思路對(duì)、代碼編譯不過(guò)”的尷尬局面。2.2 操作系統(tǒng)與計(jì)算機(jī)網(wǎng)絡(luò)客戶端開發(fā)繞不開的兩座山很多科班同學(xué)在大學(xué)里學(xué)過(guò)操作系統(tǒng)和計(jì)算機(jī)網(wǎng)絡(luò)但備考客戶端崗位時(shí)容易輕視這兩門課覺得“客戶端開發(fā)用不到那么底層的東西”。這個(gè)想法在校招筆試?yán)飼?huì)很吃虧。操作系統(tǒng)的高頻考點(diǎn)包括進(jìn)程和線程的區(qū)別、線程同步的幾種方式互斥鎖、信號(hào)量、條件變量、死鎖產(chǎn)生的四個(gè)必要條件、虛擬內(nèi)存和頁(yè)面置換算法、進(jìn)程間通信的方式。選擇題往往會(huì)給出幾個(gè)容易混淆的說(shuō)法讓你判斷正誤比如“線程是資源分配的基本單位進(jìn)程是調(diào)度的基本單位”這種經(jīng)典的錯(cuò)誤表述。而簡(jiǎn)答題可能會(huì)讓你設(shè)計(jì)一個(gè)“多線程下載”的方案任務(wù)怎么拆、線程池大小怎么定、下載失敗怎么重試、多個(gè)線程寫同一個(gè)文件如何保證數(shù)據(jù)不沖突。這已經(jīng)不只是考概念而是考你能否用操作系統(tǒng)知識(shí)解決實(shí)際工程問(wèn)題。計(jì)算機(jī)網(wǎng)絡(luò)的重點(diǎn)則集中在TCP和UDP的區(qū)別、TCP三次握手和四次揮手的過(guò)程、HTTP和HTTPS的差異、HTTP常見狀態(tài)碼的含義、DNS解析過(guò)程。由于客戶端的主要工作是網(wǎng)絡(luò)請(qǐng)求的發(fā)送和數(shù)據(jù)的解析所以HTTP協(xié)議相關(guān)的內(nèi)容考察得非常細(xì)。比如“HTTP的長(zhǎng)連接和短連接分別適用于什么場(chǎng)景”“TCP擁塞控制在弱網(wǎng)環(huán)境下對(duì)App請(qǐng)求有什么影響”這些都屬于客戶端開發(fā)的高頻面試題在筆試?yán)锿瑯訒?huì)出現(xiàn)。準(zhǔn)備這部分內(nèi)容推薦拿著Charles或Wireshark實(shí)際抓包看幾次請(qǐng)求和響應(yīng)把協(xié)議頭字段對(duì)應(yīng)到真實(shí)流量上理解深度會(huì)好很多。2.3 客戶端平臺(tái)基礎(chǔ)Android與iOS的核心機(jī)制這部分是真正區(qū)分“認(rèn)真準(zhǔn)備過(guò)客戶端開發(fā)”和“海投碰運(yùn)氣”的考點(diǎn)的環(huán)節(jié)。如果投的是Android方向Activity生命周期是必考內(nèi)容而且往往會(huì)結(jié)合場(chǎng)景出題比如屏幕旋轉(zhuǎn)時(shí)Activity會(huì)經(jīng)歷哪些回調(diào)、A頁(yè)面跳轉(zhuǎn)到B頁(yè)面時(shí)兩個(gè)頁(yè)面的生命周期回調(diào)順序是什么、App退到后臺(tái)再回來(lái)時(shí)會(huì)發(fā)生什么。這些看似基礎(chǔ)但細(xì)節(jié)非常多不同場(chǎng)景下的執(zhí)行順序很容易混淆。我的復(fù)習(xí)方法是把幾個(gè)常見場(chǎng)景的生命周期調(diào)用順序自己手寫一遍整理成表格反復(fù)對(duì)照直到完全形成條件反射。Android的消息機(jī)制、Handler和Looper的關(guān)系、主線程和子線程的通信方式也是考察重點(diǎn)。還有內(nèi)存優(yōu)化相關(guān)的內(nèi)容內(nèi)存泄漏的常見場(chǎng)景Handler持有Activity引用、靜態(tài)Context引用、未注銷的BroadcastReceiver、內(nèi)存抖動(dòng)和GC機(jī)制、ANR的原因分析和避免方式。這些都是客戶端開發(fā)日常工作中一定會(huì)遇到的問(wèn)題筆試考察它們非常合理。如果投的是iOS方向運(yùn)行時(shí)機(jī)制、消息傳遞機(jī)制、內(nèi)存管理引用計(jì)數(shù)、循環(huán)引用、多線程方案GCD、NSOperation是核心考察點(diǎn)。因?yàn)辄c(diǎn)我達(dá)的客戶端是Android和iOS雙端都在做筆試主體雖然以Android為主但也出現(xiàn)了少量iOS相關(guān)題目。我的建議是主攻一端但對(duì)另一端的基本概念至少做到“聽說(shuō)過(guò)、不陌生”避免出現(xiàn)整道題完全看不懂的情況。2.4 語(yǔ)言基礎(chǔ)Java是Android開發(fā)的根雖然現(xiàn)在Kotlin在Android開發(fā)中的占比越來(lái)越高但很多筆試仍然默認(rèn)考察Java基礎(chǔ)。比如String、StringBuilder、StringBuffer的區(qū)別HashMap的底層實(shí)現(xiàn)原理數(shù)組鏈表紅黑樹ArrayList和LinkedList的性能對(duì)比Java內(nèi)存區(qū)域的劃分堆、棧、方法區(qū)、本地方法棧、程序計(jì)數(shù)器GC回收機(jī)制和常見的垃圾收集器多線程相關(guān)的synchronized、volatile、ThreadLocal等。這些知識(shí)點(diǎn)幾乎每一場(chǎng)客戶端筆試都會(huì)出現(xiàn)屬于“送分題”和“送命題”之間的模糊地帶——真正理解了是送分半懂不懂就是送命。還有一個(gè)小眾但值得關(guān)注的知識(shí)點(diǎn)反射和注解??陀^題里可能會(huì)問(wèn)你“反射機(jī)制的性能問(wèn)題”“注解的保留策略有哪些”這其實(shí)是在考察你對(duì)框架底層原理的了解程度。現(xiàn)在的Android開發(fā)大量依賴注解和反射框架比如ButterKnife、EventBus筆試?yán)锍霈F(xiàn)相關(guān)題目并不意外。3. 編程題實(shí)戰(zhàn)解析手寫代碼的思路與細(xì)節(jié)3.1 字符串去重與排序一道典型的“基本功”題編程題中出現(xiàn)過(guò)一道這樣的題目給定一個(gè)字符串去除其中重復(fù)的字符并按照字符ASCII碼升序排序輸出處理后的字符串。這道題LeetCode上有很多變體核心考察點(diǎn)在于你能否用合理的數(shù)據(jù)結(jié)構(gòu)在O(n)時(shí)間內(nèi)完成去重再以較小的空間開銷完成排序。思路并不復(fù)雜用一個(gè)長(zhǎng)度為256的布爾數(shù)組記錄字符是否出現(xiàn)過(guò)第一遍遍歷標(biāo)記由于ASCII碼本身有序第二次遍歷時(shí)按數(shù)組順序輸出即可。這里有個(gè)容易出錯(cuò)的地方如果你只用一個(gè)HashSet去重后再轉(zhuǎn)換成數(shù)組排序整體復(fù)雜度會(huì)變成O(n log n)在大數(shù)據(jù)量下可能超時(shí)而用布爾數(shù)組的方式可以把排序步驟也變成O(1)的常數(shù)時(shí)間。代碼可以這樣寫public String removeDuplicateAndSort(String s) { if (s null || s.length() 0) { return ; } boolean[] seen new boolean[256]; for (int i 0; i s.length(); i) { seen[s.charAt(i)] true; } StringBuilder sb new StringBuilder(); for (int i 0; i 256; i) { if (seen[i]) { sb.append((char) i); } } return sb.toString(); }這道題想清楚了其實(shí)不難但我在筆試現(xiàn)場(chǎng)發(fā)現(xiàn)不少人在“排序”這一步繞了遠(yuǎn)路還有人忘了處理空字符串和null輸入。面試官看的不只是你能不能解出來(lái)還看你有沒有防御式編程的意識(shí)。寫完代碼之后多問(wèn)自己一句如果輸入是空串怎么辦如果字符包含中文怎么辦如果字符串特別長(zhǎng)怎么辦這些問(wèn)題想清楚代碼質(zhì)量會(huì)明顯上一個(gè)臺(tái)階。3.2 鏈表反轉(zhuǎn)高頻中的高頻鏈表反轉(zhuǎn)是客戶端筆試中出現(xiàn)頻率極高的題目沒有之一。點(diǎn)我達(dá)的筆試題里同樣出現(xiàn)了。題目本身很經(jīng)典給定一個(gè)單鏈表的頭節(jié)點(diǎn)將鏈表反轉(zhuǎn)返回新鏈表的頭節(jié)點(diǎn)。解題思路有三種迭代法、遞歸法、頭插法。迭代法最直觀用一個(gè)prev指針記錄前驅(qū)節(jié)點(diǎn)一個(gè)curr指針遍歷當(dāng)前節(jié)點(diǎn)每次迭代時(shí)先保存下一個(gè)節(jié)點(diǎn)再把當(dāng)前節(jié)點(diǎn)的next指向前驅(qū)節(jié)點(diǎn)。代碼大概長(zhǎng)這樣public ListNode reverseList(ListNode head) { ListNode prev null; ListNode curr head; while (curr ! null) { ListNode nextTemp curr.next; curr.next prev; prev curr; curr nextTemp; } return prev; }這道題真正坑人的地方不在基本反轉(zhuǎn)而在進(jìn)階變體反轉(zhuǎn)鏈表的第m到第n個(gè)節(jié)點(diǎn)。點(diǎn)我達(dá)的筆試編程題里有一道就是這種變體需要先找到第m-1個(gè)節(jié)點(diǎn)然后反轉(zhuǎn)中間的n-m1個(gè)節(jié)點(diǎn)最后把三段鏈表拼接起來(lái)。這里非??简?yàn)?zāi)銓?duì)指針操作的熟練度稍不留神就會(huì)在拼接順序上出錯(cuò)。我的建議是做鏈表相關(guān)題目時(shí)一定要在紙上畫圖把指針的指向變化一步一步畫出來(lái)不要直接在腦子里做指針操作。3.3 場(chǎng)景模擬題訂單列表分頁(yè)加載出了數(shù)據(jù)結(jié)構(gòu)題編程題的第二道往往是一道業(yè)務(wù)場(chǎng)景模擬題。這類題目不會(huì)直接告訴你“要用動(dòng)態(tài)規(guī)劃”或者“要用貪心算法”而是給你一個(gè)真實(shí)業(yè)務(wù)場(chǎng)景讓你自己提煉問(wèn)題、設(shè)計(jì)方案。我當(dāng)時(shí)遇到的一道題大致是這樣有一個(gè)訂單列表接口服務(wù)端支持分頁(yè)返回?cái)?shù)據(jù)每頁(yè)最多返回20條客戶端需要實(shí)現(xiàn)一個(gè)加載函數(shù)。給定一個(gè)訂單ID數(shù)組代表當(dāng)前已有的訂單再給定一個(gè)整數(shù)n代表需要加載的條數(shù)要求返回需要請(qǐng)求的頁(yè)碼列表頁(yè)碼從1開始。如果加載過(guò)程中遇到已存在的訂單需要跳過(guò)繼續(xù)加載直到湊夠n條為止。這道題本質(zhì)上是考察分頁(yè)邏輯的邊界處理和對(duì)“已有數(shù)據(jù)”的理解。解決思路的關(guān)鍵點(diǎn)在于當(dāng)某一頁(yè)的20條訂單全部已存在時(shí)不能只跳過(guò)這一頁(yè)就結(jié)束要繼續(xù)請(qǐng)求下一頁(yè)直到湊滿n條新訂單。這里非常容易出錯(cuò)很多人會(huì)忽略“整頁(yè)都重復(fù)”的情況導(dǎo)致返回結(jié)果不足n條。我給的建議是場(chǎng)景模擬題一般沒有唯一答案但你一定要在代碼里體現(xiàn)出對(duì)邊界條件的周全考慮。寫完代碼后主動(dòng)用幾個(gè)測(cè)試用例驗(yàn)證一下n為0時(shí)、已有訂單數(shù)為0時(shí)、某一頁(yè)全部重復(fù)時(shí)、最后一頁(yè)不足20條時(shí)。把這些情況都想到了代碼才算是合格的。4. 客觀題高頻易錯(cuò)點(diǎn)與排查技巧這些坑你必須提前踩過(guò)4.1 易混淆知識(shí)點(diǎn)對(duì)照表備考客觀題時(shí)最讓人頭疼的就是那些“看起來(lái)差不多實(shí)際上差很多”的知識(shí)點(diǎn)。我整理了幾個(gè)高頻易錯(cuò)點(diǎn)的對(duì)照表非常適合在考前快速過(guò)一遍易混淆點(diǎn)正確理解常見錯(cuò)誤HashMap vs HashtableHashMap允許null鍵和null值線程不安全Hashtable不允許null線程安全但性能差以為HashMap線程安全TCP vs UDPTCP面向連接、可靠、有序UDP無(wú)連接、不可靠、高效認(rèn)為UDP比TCP更穩(wěn)定Activity的onStart和onResumeonStart表示頁(yè)面可見但不可交互onResume表示可交互將兩者混為一談進(jìn)程 vs 線程進(jìn)程是資源分配的基本單位線程是CPU調(diào)度的基本單位互換兩者的定義static方法能否被重寫static方法可以被隱藏但不能被重寫認(rèn)為static方法可以正常重寫String的equals和比較引用地址equals比較內(nèi)容String重寫過(guò)用比較字符串內(nèi)容數(shù)組和鏈表的區(qū)別數(shù)組隨機(jī)訪問(wèn)快、插入刪除慢鏈表反之忽略數(shù)組擴(kuò)容的開銷這類題目沒有太多捷徑只能靠反復(fù)記憶和刷題鞏固。但有一點(diǎn)值得注意不要只看答案要理解每個(gè)選項(xiàng)“為什么對(duì)”和“為什么錯(cuò)”。因?yàn)槎噙x題經(jīng)常把幾個(gè)容易混淆的知識(shí)點(diǎn)放在一起你只有真正理解它們的區(qū)別才能在多個(gè)選項(xiàng)中做出準(zhǔn)確判斷。4.2 多選題的答題策略多選題是校招筆試?yán)锸Х肿顕?yán)重的題型很多同學(xué)不是不會(huì)而是不敢選。我的經(jīng)驗(yàn)是多選題的計(jì)分規(guī)則一般是多選、少選、錯(cuò)選都不得分所以如果你對(duì)某個(gè)選項(xiàng)只有五六成的把握建議不選。雖然這樣拿不到滿分但至少有機(jī)會(huì)拿到部分分?jǐn)?shù)——有些筆試的計(jì)分規(guī)則是按照正確選項(xiàng)數(shù)量給部分分的少選比錯(cuò)選強(qiáng)。另外多選題的選項(xiàng)設(shè)計(jì)往往有一個(gè)規(guī)律四個(gè)選項(xiàng)中至少有一個(gè)是“明顯正確”的至少有一個(gè)是“明顯錯(cuò)誤”的剩下的兩個(gè)屬于“邊緣選項(xiàng)”。先把明顯正確和明顯錯(cuò)誤的選項(xiàng)標(biāo)記出來(lái)對(duì)邊緣選項(xiàng)做分析和判斷而不是憑感覺選。這個(gè)方法聽起來(lái)沒什么技術(shù)含量但在高壓的筆試環(huán)境下非常實(shí)用能有效降低失誤率。4.3 編程題提交前的自查清單編程題寫完之后千萬(wàn)不要急著提交。我在實(shí)際筆試中總結(jié)了一個(gè)自查清單每次提交前都強(qiáng)制自己過(guò)一遍第一檢查輸入的邊界情況空數(shù)組、空字符串、null、長(zhǎng)度為1的數(shù)組、最大值和最小值。第二檢查主要變量在循環(huán)中的更新邏輯避免出現(xiàn)死循環(huán)或數(shù)組越界。第三檢查時(shí)間復(fù)雜度和空間復(fù)雜度是否滿足題目約束如果數(shù)據(jù)量是10^5級(jí)別O(n^2)的算法大概率會(huì)超時(shí)。第四檢查是否有輸出格式要求有些題目要求輸出順序、換行、大小寫等細(xì)節(jié)。第五如果時(shí)間允許在本地或腦海中選擇一個(gè)能覆蓋邊界條件的測(cè)試用例手動(dòng)運(yùn)行一遍代碼邏輯。這個(gè)流程看起來(lái)會(huì)多花幾分鐘但對(duì)正確率的提升非常明顯。校招筆試的編程題往往不是一道題定勝負(fù)而是幾道題的綜合得分決定你是否進(jìn)入下一輪。確保已提交的題目穩(wěn)定得分比冒險(xiǎn)沖擊難題更重要。5. 時(shí)間分配與答題順序決定最終成績(jī)的關(guān)鍵細(xì)節(jié)5.1 分階段的答題時(shí)間規(guī)劃120分鐘的筆試時(shí)間說(shuō)長(zhǎng)不長(zhǎng)說(shuō)短不短。如果在前面的客觀題上耗時(shí)太久后面編程題就只能草草收?qǐng)鋈绻w速掠過(guò)客觀題又容易在一些基礎(chǔ)概念題上白白丟分。我自己的時(shí)間分配方案是前60分鐘做完全部客觀題和簡(jiǎn)答題留下60分鐘給編程題。如果客觀題做得順利還能把節(jié)省下來(lái)的時(shí)間勻給編程題做更充分的測(cè)試。具體到每道題的時(shí)間控制單選題平均每題不超過(guò)1.5分鐘多選題每題不超過(guò)2.5分鐘簡(jiǎn)答題每題不超過(guò)10分鐘。如果在某道題上超過(guò)這個(gè)時(shí)間還沒有明確思路立即標(biāo)記并跳到下一題。筆試系統(tǒng)一般支持題號(hào)跳轉(zhuǎn)回頭再看完全來(lái)得及。很多同學(xué)在時(shí)間壓力下容易陷入“不甘心跳過(guò)”的心理狀態(tài)但這在筆試?yán)锸谴蠹?。一道兩分的選擇題花十分鐘死磕就算做對(duì)了從收益上看也是虧的。5.2 簡(jiǎn)答題的答題結(jié)構(gòu)與表達(dá)技巧簡(jiǎn)答題是容易被忽視的失分點(diǎn)。這類題目往往考察你對(duì)某個(gè)機(jī)制或方案的理解深度比如“請(qǐng)說(shuō)明Android中Handler機(jī)制的工作原理”“如何優(yōu)化App的啟動(dòng)速度”。很多同學(xué)的答案是“想到哪寫到哪”缺乏結(jié)構(gòu)導(dǎo)致閱卷人難以快速抓到你的核心觀點(diǎn)。我在分享一個(gè)比較實(shí)用的答題框架先給出核心結(jié)論再展開分點(diǎn)解釋最后補(bǔ)充一個(gè)實(shí)際案例或踩坑經(jīng)驗(yàn)。比如回答“如何優(yōu)化App啟動(dòng)速度”可以先說(shuō)“啟動(dòng)優(yōu)化主要從三個(gè)方面入手減少主線程任務(wù)、延遲初始化非必要組件、優(yōu)化布局加載”然后分別展開解釋具體手段最后結(jié)合自己項(xiàng)目中遇到的問(wèn)題舉一個(gè)實(shí)例。這樣的回答結(jié)構(gòu)清晰信息密度高閱卷人一眼就能看出你有實(shí)際項(xiàng)目經(jīng)驗(yàn)而不是在背面經(jīng)。簡(jiǎn)答題寫得有層次感實(shí)際是一種成本極低的加分方式。它不需要你掌握額外的知識(shí)只需要你把已經(jīng)會(huì)的知識(shí)點(diǎn)組織得更清晰。5.3 編程題的取舍原則編程題通常有兩道分值相同。遇到兩道題難度不均的情況時(shí)我的建議是先做自己更有把握的那一道把確定性分?jǐn)?shù)先拿到手。不要在偏難的那道題上花掉全部時(shí)間最后兩道題都沒做完。這個(gè)取舍原則在筆試界有一個(gè)很形象的類比這就像搞開發(fā)時(shí)做技術(shù)選型穩(wěn)定可用的方案優(yōu)先級(jí)永遠(yuǎn)高于花哨但不成熟的方案。校招筆試不是競(jìng)賽它的目的是篩選出基礎(chǔ)扎實(shí)、代碼能力合格的人而不是尋找能在45分鐘內(nèi)做出算法難題的天才。把自己會(huì)的題目做對(duì)、做完整、做得干凈已經(jīng)能超過(guò)大部分候選人了。6. 筆試后的復(fù)盤與下一步準(zhǔn)備6.1 筆試后的復(fù)盤方法筆試結(jié)束并不代表整個(gè)流程結(jié)束。無(wú)論結(jié)果如何認(rèn)真復(fù)盤這場(chǎng)筆試都是提高自己競(jìng)爭(zhēng)力的關(guān)鍵一步。復(fù)盤不是“對(duì)一下答案看看自己得了多少分”而是要追溯每道錯(cuò)題背后的知識(shí)盲區(qū)。我在每一次筆試后都會(huì)做一件事把客觀題中所有拿不準(zhǔn)的選項(xiàng)全部整理到錯(cuò)題本里無(wú)論這道題最終是否答對(duì)。因?yàn)椤澳貌粶?zhǔn)但蒙對(duì)了”和“做錯(cuò)了”本質(zhì)上沒有區(qū)別都說(shuō)明對(duì)應(yīng)的知識(shí)點(diǎn)沒有徹底掌握。對(duì)編程題復(fù)盤時(shí)要把自己的解法改寫一遍并嘗試用更優(yōu)的思路重新實(shí)現(xiàn)。比如一道用雙循環(huán)暴力解決的題復(fù)盤時(shí)能否用HashMap優(yōu)化到O(n)一道用遞歸解決的題復(fù)盤時(shí)能否用迭代實(shí)現(xiàn)來(lái)規(guī)避棧溢出的風(fēng)險(xiǎn)這種“一題多解”的復(fù)盤方式對(duì)算法能力的提升效果立竿見影。我認(rèn)識(shí)的一個(gè)朋友就是靠三輪筆試復(fù)盤把算法題的解題速度提升了將近一倍。6.2 為后續(xù)面試做知識(shí)儲(chǔ)備筆試只是校招的第一關(guān)通過(guò)筆試后還有面試環(huán)節(jié)。在準(zhǔn)備面試時(shí)筆試中出現(xiàn)過(guò)的知識(shí)點(diǎn)往往具有很強(qiáng)的參考價(jià)值——因?yàn)槊嬖嚬俸芸赡軙?huì)就這些知識(shí)點(diǎn)繼續(xù)追問(wèn)。比如筆試考了Handler機(jī)制面試時(shí)就可能讓你手寫一個(gè)簡(jiǎn)化版的Handler筆試考了自定義View的測(cè)量和繪制流程面試時(shí)就可能讓你現(xiàn)場(chǎng)講一下View的繪制流程在緩存優(yōu)化時(shí)怎么把控甚至給出一段代碼讓你分析性能問(wèn)題。所以筆試復(fù)盤整理的錯(cuò)題本和知識(shí)清單要一直保留到整個(gè)校招季結(jié)束隨時(shí)補(bǔ)充新的內(nèi)容。我個(gè)人的習(xí)慣是把面試中被追問(wèn)到的知識(shí)點(diǎn)加入同一份清單標(biāo)注“筆試已考”“面試已問(wèn)”和“掌握程度”三個(gè)字段形成自己的知識(shí)圖譜。這樣復(fù)習(xí)起來(lái)非常有針對(duì)性不會(huì)漫無(wú)目的。6.3 保持心態(tài)與節(jié)奏最后想聊聊心態(tài)。校招筆試和面試密集安排的那段時(shí)間幾乎每個(gè)人都會(huì)經(jīng)歷被拒、拿到面試機(jī)會(huì)、等待結(jié)果這種情緒上的起伏。有一些筆試你感覺自己發(fā)揮得不錯(cuò)結(jié)果卻沒有進(jìn)下一輪有一些筆試你覺得考砸了反而意外通過(guò)了。這是非常正常的現(xiàn)象因?yàn)楣驹诤Y選候選人時(shí)會(huì)參考多項(xiàng)指標(biāo)筆試成績(jī)只是其中之一。我的經(jīng)驗(yàn)是不要試圖從單場(chǎng)筆試的結(jié)果中過(guò)度解讀自己。把每一場(chǎng)筆試當(dāng)作一次模擬練習(xí)考完之后客觀記錄自己的表現(xiàn)找到薄弱環(huán)節(jié)然后投入到下一階段的準(zhǔn)備中去。計(jì)算機(jī)基礎(chǔ)這門課沒有捷徑但也沒有天花板——你把一個(gè)知識(shí)點(diǎn)弄懂之后它就會(huì)一直長(zhǎng)在你身上。保持節(jié)奏穩(wěn)步推進(jìn)最后一定能拿到心儀的offer。