
作為一個經歷過校招、也做過面試官的人我太清楚“京東2017校招編程題”在技術圈的分量了。那一年京東的筆試題目質量相當高雖然沒有特別偏難怪的題但勝在全面基礎、算法、思維一個不落。很多題后來被各大公司的題庫反復引用直到今天你在牛客網、力扣上依然能看到它們的變體。趁著最近又有不少讀者在后臺問我“校招編程題該怎么刷”、“京東的題難不難”我把當年那套題重新扒出來結合我自己的解題記錄和后來做面試官時看到的考生常見錯誤做一次系統的拆解。這篇文章不是簡單地貼題目和答案而是想告訴你每一道題背后到底在考什么出題人希望看到你具備哪些能力以及當你拿到一道陌生編程題時應該用什么樣的思維路徑去拆解它。無論你是正在準備校招的應屆生還是工作幾年想回頭補基礎的同學這份梳理應該都能幫到你。1. 京東2017校招編程題的整體畫像到底在考什么先給沒參加過那場筆試的同學還原一下當時的場景。京東的校招筆試通常是線上筆試編程題部分一般有2到3道時間大概在1到1.5小時之間。你不僅要寫對還得寫得快、寫得穩。2017年的題目整體風格非常“京東化”——務實、貼近業務場景、不追求偏怪難但對基礎數據結構和算法的要求一點都不含糊。1.1 核心考察方向基礎算法能力而不是炫技我那年刷完題后又把能找到的版本都做了一遍最大的感受是這組題考察的核心是“你是否具備扎實的計算機基礎功”。它的題目類型主要集中在字符串處理與模擬基礎動態規劃圖論與搜索尤其是網格類場景數學推導與規律發現集合與哈希表的高效應用你會發現它沒有那種要求你三分鐘默寫紅黑樹的變態問題也沒有需要半小時推公式的數學競賽題。但它會把你要解決的問題藏在業務場景里。比如“分蘋果”、“找最少步數”、“字典序排列”這類題表面上是生活化描述骨子里考的卻是DP、BFS、貪心這些經典算法。1.2 難度分布與題量結構根據我找得到的真題回憶匯總2017年京東筆試的編程題大致呈階梯式分布第一題通常是純送分題考字符串操作或者簡單模擬細心就能全對。第二題進入中等難度一般是DP或者二分查找的變體需要你能準確建模。第三題開始區分度就出來了要么是圖上搜索要么是帶有數學規律的構造題需要你不僅會算法還能優化常數。這三題做下來基本就能把一個候選人的編碼能力、算法功底、調試能力、心理素質看得七七八八。說實話三年后我坐在面試官的位置上看候選人筆試代碼時依然會拿當年這組題當尺子。它不高級但真的能量出水平。1.3 為什么今天仍值得刷這套題有讀者可能會問2017年的題放到現在還有參考價值嗎我明確告訴你有而且價值不小。原因有三第一校招筆試的核心考察能力這些年沒有變依然是算法功底加編碼實現力。這套題的考察維度完全不過時。第二京東這套題在難度設置上非常“經典”既不像某些公司那樣入門勸退也不像另一些公司那樣全是模板題。它處在一個恰到好處的“能力探測區間”。第三這組題中的很多原題或變體后來反復出現在其他公司的題庫中。你刷熟了這一套等于同時做了好幾家公司的準備。2. 高頻考點拆解把題目變成知識點地圖刷題最忌諱的就是“就題論題”。寫出一道題過兩天換了個皮又不會了。這本質上是沒有完成“題目到知識點”的抽象過程。我當年刷完京東這套題后專門做了一張知識點地圖今天分享給你。2.1 字符串處理類細節決定成敗這類題屬于“看起來簡單做起來想摔鍵盤”的類型。京東的筆試里字符串題經常是第一題但它的坑從來不藏在算法里而是藏在邊界條件和特殊情況里。舉個例子當時有道題是“給定一個字符串刪除其中所有重復字符且保持第一次出現的順序”。我見過很多人的第一反應是“用HashSet邊遍歷邊去重”思路確實對但寫出來卻各種小問題有人忘了處理空字符串有人忽略了字符大小寫是否敏感有人沒有考慮字符集范圍。你去看官方題解會覺得這也太小兒科了但考場上全對的人就是不多。字符串題的復習重點應該放在遍歷邊界、字符集范圍、輸入輸出格式、大小寫/空格的處理、以及代碼的健壯性。這些能力沒法靠背模板獲得只能靠大量手寫代碼形成肌肉記憶。2.2 動態規劃與狀態定義區分度的分水嶺如果字符串題是熱身那動態規劃題就是校招筆試真正的分水嶺。京東2017的題目里至少有三分之一的題需要用到DP思想。很多人學DP的通病是“狀態方程看不懂看懂了也不會推”。我提供一個親測有效的方法拿到一道DP題先別急著寫遞推公式而是先問自己三個問題我關注的結果是什么比如最大價值、最小步數、方案總數我在決策的過程中哪些信息是必須記住的這就是狀態維度的來源每一步決策和上一步的關系是什么這就是狀態轉移方程以京東考過的那道“分蘋果”來說很多人的第一反應是搜所有方案但n一旦變大組合爆炸。用我上面的三個問題來拆解關注的是“最少搬動幾次”必須記住“當前蘋果數”和“已搬動次數”每一步可以搬1、2或3個——這就是一個非常標準的“最少步數到達目標”的動態規劃模型狀態轉移方程其實就是dp[i] min(dp[i-1], dp[i-2], dp[i-3]) 1。我當時在博客里寫過一句話今天依然覺得是對的動態規劃不考智商考的是你有沒有建立“狀態”這個概念的習慣。2.3 圖論與搜索網格題里的陷阱與突破京東的題里還有一類非常高頻給定一個網格或者地圖求從起點到終點的最短路徑、最少步數、或者判斷是否可達。這類題幾乎就是為BFS量身定制的。但是請相信我這類題拿到滿分遠比想象中難。因為網格題的坑不在算法本身而在工程細節。方向數組寫錯了會導致全部走偏visited數組忘記標記會導致隊列內存爆炸對越界條件的判斷順序寫錯了甚至會造成數組越界訪問。我當時做過一個統計筆試中BFS題做錯的人里有將近一半是掛在“邊界檢查”和“visited標記”這兩個細節上。它不考你懂不懂BFS原理考的是你代碼寫得好不好。2.4 數學思維與規律題最后的亮點京東的題還有一個特色時不時會出現一道看起來像數學競賽、實際上是編程題的題目。這類題往往是整套卷子的“小彩蛋”區分度極高。我印象最深的是一道跟“數字和”相關的題給定一個正整數每次操作可以將其替換為各個數位之和問多少次操作可以變成一位數。很多人拿到之后就寫循環、求數位和、再循環。這個沒錯但如果出題人把測試數據范圍調大到10^18以上你的解法就需要優化。這里其實藏著一個“數學優化”的關鍵不是等數位和小于10才停下來而是直接用一次“數位和模9”的技巧判斷。類似的規律題你不知道這個規律時怎么寫都覺得別扭知道了以后三行代碼解決問題。這就是數學思維的價值。3. 典型題目精講從讀題到AC的完整推演前面講了考什么現在我們來實戰。我挑了幾道有代表性的題目帶著你走一遍從讀題到AC的完整思考過程。我不會只貼一個標準答案而是把每一步的思維過程、備選方案、以及我會踩的坑都攤開給你看。3.1 題目一數字序列拼接我們先從一道常見題入手。題目大致是給定n個正整數將它們拼接成一個新數問怎么拼接可以得到最大的數。比如輸入[3, 30, 34, 5, 9]能拼成的最大數是9534330。很多人的第一直覺是“按字典序從大到小排”但一提交發現連示例都過不了。問題出在哪因為“3”和“30”這兩個數按字典序“3”的確比“30”大但拼接結果是330而另一個順序是303顯然前者更大。可如果你把“9”和“98”放一起“9”字典序比“98”大但拼接“998”確實大于“989”所以這組又沒問題。你稍微多試幾組就會發現其實這是一個自定義排序問題。正確的做法是定義一個新的比較規則——對于字符串a和b如果“ab”大于“ba”則a應該排在b前面。用Python寫的話核心就兩行from functools import cmp_to_key def largest_number(nums): strs list(map(str, nums)) strs.sort(keycmp_to_key(lambda a, b: -1 if ab ba else 1)) result .join(strs).lstrip(0) return result or 0這道題給我的啟發是當直覺的排序規則不成立時不要死磕而是回到定義本身重新定義“誰在誰前面”的比較關系。這個思維模式不僅適用于這道題很多需要自定義排序的算法題都靠它。3.2 題目二快速求整數各個數位之和的實現這道題看起來像是來送分的輸入一個整數求它各位數字的和。有人會說這也算編程題但請注意當測試數據的范圍達到10^18甚至更大的時候部分語言的基本類型就會溢出同時用字符串處理時的效率也會有差別。最穩妥的實現方式是先轉字符串再逐位累加或者用取模運算def digit_sum(n): total 0 while n: total n % 10 n // 10 return total這樣寫代碼非常短但對于極端的大整數如果題目允許用字符串輸入那么直接遍歷字符更穩妥。我見過不少同學在考場上直接用int接收輸入然后發現溢出報錯心態直接崩了。所以這種看似幼稚的題反而是最值得警惕的。通常這種“送分題”里還有隱藏考點比如數位和能不能被3整除、能不能被9整除。判斷某個數是否被3整除可以不用算完整數位和因為一個數模3等于它的數位和模3模9同理。很多后來的筆試題都直接用了這個結論。記住有時面試官不是考你會不會循環而是考你知不知道背后的數學性質。3.3 題目三帶狀態的網格最短步數問題這是2017年京東筆試里最有區分度的一道題。題目描述是這樣的在一個m行n列網格中0表示空地1表示障礙物。玩家從左上角出發想到達右下角每次可以向上、下、左、右四個方向移動。現在你有一個特殊能力可以使用一次使用后可以“跳過”一個障礙物。問最少需要多少步。如果你沒有做過帶狀態的BFS第一次看到會有點懵單純BFS求最短路徑可以但“可以跳過障礙物一次”這個條件怎么處理實際上這個題目需要把一個普通的節點狀態拆成兩個沒使用能力前和使用能力后。如果你在沒使用能力時到達某個節點但是后來你用掉了能力你的可選路徑就變了所以你不能僅僅用一個二維visited來記錄而要用三維數組visited[x][y][used]來記錄狀態其中used取0或1。搜索的過程是從起點開始如果當前位置是空地兩個狀態都可以轉移如果是障礙物且未使用能力可以使用能力進入used1的狀態如果是障礙物且能力已使用則不能進入。終點可以是used0或used1的任意一種。由于BFS按層擴展第一次到達終點時一定是最小步數。我當時第一次寫這道題的代碼時因為方向數組的順序寫錯了導致搜索路徑不是最小卡了將近半小時。后來發現了這個低級錯誤真的是哭笑不得。所以我真誠建議每位準備筆試的同學方向數組最好固定為“上、下、左、右”和坐標數組一一對應就不要再改了免得自己把自己繞暈。認真說這道題是BFS進階的基礎也是很多“至少使用K次道具”問題的雛形后來我在不少大廠的題庫里都見到過類似模型。3.4 題目四股票買賣的最佳時機變體2017年京東也考過買賣股票的問題但它的變體比較特殊不是一次買賣也不是無限次買賣而是限定了最多兩次交易。原題通常是這樣說的給定一個數組它的第i個元素是一支給定股票第i天的價格。設計一個算法來計算你所能獲取的最大利潤最多可以完成兩筆交易。很多人第一次接觸時直接懵了不知道該從哪個角度拆。其實這個題是DP的經典變體有兩種比較普適的做法。第一種做法是“分段法”因為最多兩筆交易一定存在一個分界點第一次交易在分界點左邊完成第二次在右邊完成。所以我們可以先從左往右預處理出“到第i天為止進行一次交易能獲得的最大利潤”再從右往左預處理出“從第i天開始進行一次交易能獲得的最大利潤”然后枚舉分界點答案就是兩者之和的最大值。用代碼來寫大概是這樣的def max_profit(prices): n len(prices) if n 2: return 0 left [0] * n right [0] * n # 從左往右 min_price prices[0] for i in range(1, n): left[i] max(left[i-1], prices[i] - min_price) min_price min(min_price, prices[i]) # 從右往左 max_price prices[-1] for i in range(n-2, -1, -1): right[i] max(right[i1], max_price - prices[i]) max_price max(max_price, prices[i]) ans 0 for i in range(n): ans max(ans, left[i] (right[i1] if i1 n else 0)) return ans第二種做法是狀態機DP。把整個過程當成四個狀態第一次買入、第一次賣出、第二次買入、第二次賣出然后不斷更新。這個思路從原理上來說更通用擴展性更強。但在這道題上分段法更好理解、編碼也更快應對筆試更實際。這道題的價值在于它訓練的是“把復雜交易拆成獨立可優化的子問題”的能力。這個思路在后續很多難題里都能復用。3.5 題目五集合與哈希表的經典配合還有一道印象很深的題是“給定一個整數數組找出其中沒有出現的最小正整數。”比如數組是[3, 4, -1, 1]答案就是2如果數組是[1, 2, 0]答案就是3。暴力解法很簡單把所有數放進哈希集合然后從1開始逐個檢查是否在集合里。時間復雜度O(n)空間復雜度O(n)。筆試里這么做已經能過了。但如果面試官追問“能不能做到O(1)空間”相信很多人會卡住。我當時總結的O(1)空間做法是把數組本身當成哈希表利用下標與數值的對應關系。具體思路是將所有在[1, n]范圍內的數放到它對應的下標位置即讓nums[i] i1然后遍歷數組第一個不滿足的位置就是缺失的最小正整數。這個技巧叫“原地哈希”在“找缺失數”“找重復數”這一系列問題里非常常用。Python代碼如下def first_missing_positive(nums): n len(nums) for i in range(n): while 1 nums[i] n and nums[nums[i]-1] ! nums[i]: nums[nums[i]-1], nums[i] nums[i], nums[nums[i]-1] for i in range(n): if nums[i] ! i 1: return i 1 return n 1很多同學看不懂這個while循環在干嘛。我解釋一下它做的事情是“不斷把當前i位置的數交換到它該去的位置”直到當前位置的數要么不在[1,n]范圍內要么它已經待在正確的位置上。交換后i位置又來了一個新數就繼續處理所以要套一層while。這道題展示了“如何用常數輔助空間解決看似需要哈希表的問題”也常作為面試現場手撕環節的考察題。刷透它能給你帶來不少底氣。4. 解題效率與代碼風格如何讓閱卷官眼前一亮寫完題目答案只是第一步。我做過面試官之后才真正體會到閱卷官看一份筆試代碼時注意力是非常有限的。一個人如果代碼寫得清晰、規范、有注釋、邊界處理到位即使算法不是最優解也能在閱卷官心里拿高分。相反即使AC了如果代碼一團亂麻也容易被扣印象分。4.1 筆試中的高分段代碼長什么樣根據我的經驗能拿高分的代碼通常具備以下特點變量命名有意義。用i、j、k本身不是錯但如果能用start、end、cur、prev這樣語意明確的命名閱讀體驗會好很多。邊界處理前置。空數組、空字符串、只有一個元素的數組這一類特殊輸入的處理一定要在函數開頭就寫好。關鍵邏輯有注釋。不是說每行都注釋而是在狀態轉移、搜索剪枝、邊界判斷這些關鍵點用一行中文或英文點明你的思路。不做多余操作。一眼就能看出的無用代碼、重復計算比報錯的代碼更讓人崩潰。我見過一位候選人在筆試卷上寫了一段BFS代碼里居然帶了完整的輸入輸出調試信息沒刪掉這給人留下的印象非常不專業。考場上時間再緊也一定要養成提交前清理調試代碼的習慣。4.2 從“能AC題目”到“高質量編碼”的三個層次我把自己的編碼能力提升路徑總結成三個階段你看看自己在哪個位置第一階段能針對個別題目寫出正確答案但思路依賴“背模板”換一道新題就卡殼。第二階段能自主推導常見算法套路知道BFS、DFS、DP、二分這類算法分別適用于什么場景寫出來的代碼格式規范邊界問題考慮齊全。第三階段能通過建立“模型映射”把新題快速歸類為已知的算法模型并且能在有限時間內完成編碼和驗證。京東2017這組題恰恰就是幫你從第一階段走向后續階段的絕佳訓練材料。它沒有超綱內容也不依賴偏門技巧只要你認真做、認真總結每一題都能轉化為你的通用能力。我特別建議你把每道題都做三遍第一遍不設限怎么順手怎么寫第二遍限制時間模擬筆試環境第三遍嘗試用不同的解法來實現對比時間和空間復雜度。這樣做完一套題收獲會非常顯著。4.3 考場時間分配策略還有一點非常關鍵的考場心得編程題的題量通常不多但每道題需要調試的時間常常比你預想的長。我的建議是開考后先快速掃一遍所有編程題判斷每道題對自己來說是大題還是小題。如果遇到一眼就有思路的題盡快寫寫完了先別急著交留時間檢查邊界。如果遇到完全沒有思路的題先跳過去做后面的題保證能拿到的分一分不丟。等基礎題都AC了再回頭啃難題心態完全不同。一個我反復強調的細節是筆試系統一般要求你提交完整代碼而不是只提交函數體但很多在線編程平臺會自動幫你處理輸入輸出所以你只需要實現核心函數。如果你不確定平臺規則第一題可以先花30秒做一個“空函數提交”測試看看返回什么再決定后續的寫法。這個技巧雖小但能幫你避免格式錯誤帶來的無謂扣分。5. 常見問題與獨家避坑指南最后這個部分我把自己備考和后來輔導學弟學妹過程中最常見的坑給揪出來。這里面既有技術層面的也有心態層面的希望你能繞開。5.1 刷題數量至上方向跑偏的典型表現“我刷了500題為什么筆試還是掛”每次聽到這句話我就想問你是刷了500題還是把同一道題做了500遍刷題的作用不是讓你“見過更多題”而是讓你“在遇到沒見過題時有足夠的解題套路可用”。我見過太多考生寫了一道京東真題看完題解覺得“哦原來是DP”然后馬不停蹄刷下一題。這是完全無效的。正確姿勢是做完一道題后至少做三件事——第一不看題解重新寫一遍第二總結這道題屬于哪個算法模型第三找到一兩道同類型的題趁熱打鐵鞏固。所以不必貪多能把京東這套題做到這種程度筆試基本就穩了。5.2 閱讀輸入不仔細最容易控制的高頻扣分點京東的筆試題有一個特點就是題干往往較長有很多業務化的描述。有些同學讀題讀到一半就迫不及待開始編碼結果寫完才發現“哦原來輸入不止一組數據”或者“原來要按照字典序輸出”。我的習慣是讀題階段至少花兩分鐘把第一段題目描述和最后一段輸入輸出說明都完整看完再動手。如果題目上說“多組測試數據”就要記得外層套一層while循環。對這種問題我建議你在草稿紙上寫下輸入類型、輸出要求、邊界條件、是否多組四個要點再動筆。5.3 過度追求最優解筆試中的隱形殺手剛刷題的人容易陷入一種心態看到一道題總想找到傳說中的“最優解”仿佛不用上最高級的算法就對不起這道題。但筆試拼的是分數分數是按測試點算的。你能用O(n^2)的算法AC一個n10^4的題你是拿滿分你用O(n)的算法想了半小時沒寫出來你拿零分。我見過不少真實案例都是因為“想在考場上給一個優雅解”反而把時間耗盡。正確的策略是先寫暴力解法拿基礎分再考慮優化。暴力解并不是丟人它在很多情況下是通往最優解的第一步。5.4 真題和變體之間的學習留白還有一個秘密很多人刷真題時沒有意識到京東這套題中的很多題后來都在其他公司的考試中“換殼登場”。比如股票買賣、網格最短步數、最小正整數缺失分別套過“兼職賺錢”“尋寶地圖”“整理工牌”之類的故事外殼。所以學習時務必把題目還原成算法模型來記憶看到“求最少步數”聯想到BFS或DP看到“最大利潤”聯想到狀態機或二分貪心看到“缺失數字”聯想到原地哈希或位運算。背書是背不完的但把模型練熟了萬變不離其宗。5.5 心態與健康筆試最后的隱形競爭力最后一個看似和編程無關、實際上非常影響發揮的點就是身體狀態和心態。筆試通常需要連續高強度用腦兩小時如果前一晚熬夜刷題第二天精神狀態一定很差。我自己當年筆試前夜就是失眠加焦慮第二天寫代碼的時候腦子像灌了漿糊本來能做出來的題愣是卡了四十分鐘。后來我給自己定了一個規矩筆試前一天不再碰新題只簡單復習筆記和錯題晚上11點前上床不帶手機進臥室第二天開考前做十分鐘深呼吸。這個習慣一直保留到我后來工作后的每一次線上技術考核。聽起來很玄學但實測非常有效。基本功是平時積累的考場上比的是誰發揮得穩。把自己調整到能打出全部水平的狀態比多刷十道題重要得多。京東2017校招編程題這套題我一直認為它是校招筆試訓練的“黃金材料”難度適中、考點全面、和業務結合緊密。如果你正在準備技術崗校招不妨把這套題認真吃透甚至可以做上兩遍三遍。這個過程中收獲的絕不僅僅是幾道題的答案而是一套能陪伴你整個職業生涯的算法思維和編碼習慣。