搞技术这行每年都有新人问要不要刷老题我的答案一直很明确要刷而且得认真刷。尤其是腾讯这种级别的公司2016年那套研发工程师笔试题放到今天来看依然是检验计算机基础功底的试金石。因为大厂要的不是你会背多少API而是看你面对一个具体问题时脑子里有没有清晰的算法思维、工程取舍和底层认知。这套题考的东西——数据结构、算法、操作系统、C底层——恰恰是日常写业务代码时最容易被忽略、但一旦遇到性能瓶颈或疑难Bug又最救命的东西。这篇文章我就以这套题作为引子把里面涉及的考点、解题思路、以及背后的原理掰开揉碎讲清楚。不管你是准备春招秋招的在校生还是工作几年想跳槽的老兵只要还想在研发这条路上走下去这篇文章都值得你花二十分钟读完。我会结合真实面试场景告诉你在拿到一段算法题或一个系统设计问题时应该怎么去拆解、怎么去选型、怎么去用代码落地以及那些“面试官不会明说但心里有杆秤”的隐藏评分点。1. 2016年这套题到底在考什么1.1 核心考点不是题目本身而是背后的知识树很多人一上来就埋头刷题把“做过”当成“会了”这是最大的误区。2016年腾讯这套研发笔试题表面上看是几道算法题加几道C/操作系统题实际上它考察的是一个研发工程师从理论到实践的四层能力结构能力层级考察内容对应题目类型实际工作映射第一层语言功底C内存模型、指针、STL实现原理选择题程序输出题线上Crash排查、性能优化第二层数据结构链表、树、哈希、堆的灵活运用算法编程题业务系统的数据建模与查询设计第三层算法设计排序、分治、动态规划、贪心思路手写代码题复杂业务逻辑的抽象与效率提升第四层系统思维并发、内存分配、进程线程模型问答/分析题高并发服务架构与稳定性保障这套题最聪明的地方在于它不考偏题怪题每个题都扎根于基础知识但你要是只背结论不去理解原理很多题你拿到手会感觉“好像见过”一写就错。举个典型的例子有一道关于快排的题目表面上问时间复杂度实际隐藏考点是“当数据量极大且存在大量重复元素时朴素快排会退化到O(n²)此时三路快排才是最优解”。这个知识点没读过《算法导论》或没在真实海量数据处理场景里碰过壁的人是答不好的。1.2 为什么2016年的老题到现在还有参考价值可能有人会问互联网技术这十年发展这么快2016年的题早该过时了吧完全不。腾讯笔试的风格一直是“重基础、轻框架”这套题里没有一道涉及当时热点的高并发框架或分布式中间件全部是计算机领域十几年不变的核心知识。可以这么说技术框架迭代很快但数据结构、算法复杂度分析、内存管理底层原理、操作系统调度逻辑这些东西十年二十年都不会变。它们就像武术里的马步和冲拳招式花样再多最后拼的还是这些基本功。所以现在拿这套题来做训练恰恰能帮你把基础打扎实再去看新框架的源码你会发现自己理解的速度完全不同。比如你在读Redis源码时看到跳跃表如果你在笔试题里已经手写过有序链表的插入删除理解起来就会非常顺滑如果你只是背过“Redis用跳跃表实现有序集合”那看源码还是一个头两个大。1.3 笔试和面试的共同底层逻辑面试官的“完形填空”考察法我在带团队做技术面试时经常用一句话形容笔试考察法“面试官给了一个残缺的题干实际想看的是你补全上下文的方式。”也就是说题目本身是“形”你暴露出来的思维过程才是“意”。以这套题里的字符串类题目为例它不会直接告诉你“请用KMP算法”它会说“寻找一个字符串在另一个字符串中出现的位置”。这时候你的思考路径非常关键如果你直接写暴力匹配说明你的基础停留在“能跑就行”层面如果你先分析暴力匹配的最坏时间复杂度O(n*m)再指出数据量增大后不适用说明你有工程风险意识如果你能进一步写出KMP的next数组构建过程并解释为什么next数组能避免重复匹配说明你真正理解了字符串匹配的核心优化点如果你还能补一句“当模式串很短时暴力匹配因为有局部性优势实际未必慢”那恭喜你你已经是“有实战经验的工程师”而不是“刷题机器”了。这套2016年的卷子每一道题都留了这么一层递进空间你能不能抓住它直接决定了面试官在几十份答卷中给你的定级。2. 核心细节拆解一道典型题目背后的完整知识链2.1 从“判断链表是否有环”看数据结构题的标准解法先看一道这套题里很有代表性的题目判断一个单链表是否存在环并找到环的入口节点。这题在LeetCode上是142号题但2016年这套笔试题里它考察的方式更偏向面试交流要求你不仅要写出代码还要解释清楚为什么这样做是正确的。标准的做法是快慢指针。慢指针每次走一步快指针每次走两步如果链表有环两个指针一定会在环内相遇。我第一次给新人讲这个题的时候他们最常问的问题是“为什么快指针走两步而不是三步、四步”原因是当慢指针进入环的入口时快指针已经在环内某个位置了。此时每走一次快指针相对慢指针靠近一步。如果快指针每次走两步那么每轮迭代距离缩短1如果快指针走三步距离缩短2仍然能相遇但存在一种边界情况——如果环的长度恰好是快慢速度差的倍数就会出现快指针永远“恰好错过”慢指针的极端场景吗其实不会因为单链表环是单向的快的每次比慢的多走k步只要k和环长不互质需要多走几轮而已最终一定追上只是可能需要更多轮数。所以两步是“简单、无脑、保证相遇”的最优选择。struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(nullptr) {} }; ListNode* detectCycle(ListNode* head) { ListNode* slow head; ListNode* fast head; while (fast fast-next) { slow slow-next; fast fast-next-next; if (slow fast) { ListNode* ptr head; while (ptr ! slow) { ptr ptr-next; slow slow-next; } return ptr; } } return nullptr; }找到相遇点之后环入口的定位有个经典推导结论从相遇点继续走同时用一个新指针从头节点出发两个指针每次都走一步它们相遇的位置就是环入口。为什么因为从链表头到环入口的距离等于从相遇点继续走到环入口的距离这是由快慢指针步数关系的公式推导出来的。这个结论你光记住没意义笔试时如果面试官追问一句“推导一下”你最好能现场在纸上画出来。我在实际辅导过的人中能在十分钟内独立推导出这个结论的大概只有四成其余的人都是靠背。而靠背在压力面试中很容易被连续追问到漏洞。2.2 二叉树遍历递归转迭代背后的栈模拟思想这套题里还有个很有意思的考点二叉树的后序遍历非递归版。很多人觉得递归多简单为什么非要转迭代因为在真实工程环境里递归深度受系统栈大小限制树的深度如果达到几万层比如处理一个极端倾斜的树形目录结构递归写法直接爆栈。所以大厂笔试考察非递归遍历本质上是在考察你有没有“系统资源意识”。非递归后序遍历比前序和中序都麻烦因为需要保证左子树、右子树都访问完才访问根节点。一种高效的解法是“双栈法”或者“反转前序法”。这里我分享一个我用着最顺手的写法基于栈上次访问节点标记vectorint postorderTraversal(TreeNode* root) { vectorint result; stackTreeNode* st; TreeNode* lastVisited nullptr; TreeNode* cur root; while (!st.empty() || cur) { if (cur) { st.push(cur); cur cur-left; } else { TreeNode* peek st.top(); if (peek-right lastVisited ! peek-right) { cur peek-right; } else { result.push_back(peek-val); lastVisited peek; st.pop(); } } } return result; }这段代码的思路是一直往左走到底把沿途节点全部入栈不能再走的时候取栈顶看右子树如果右子树存在且没访问过就往右走否则访问当前节点并弹栈。我用这个写法参加过多场技术分享几乎每次都能遇到现场听众问同样的问题“如果右子树为空怎么办”答案很简单右子树为空时就不需要入栈直接访问当前节点即可代码里的if (peek-right lastVisited ! peek-right)严格判断了这种情况。2.3 字符串的全排列问题回溯法这道“通用解法模板”字符串或数组的全排列几乎是大厂笔试的常青树2016年腾讯这套题也有一道。它表面上是让你输出所有排列实际上考察的是回溯法Backtracking的通用框架做选择、递归进入子问题、撤销选择。这里特别值得说的是2016年那会儿很多人还在用交换法做全排列这种思路对“字符不重复”的场景是够用的但一旦出现重复字符比如“aab”直接交换法会产生大量重复排列需要在递归前加一个剪枝判断同一层递归中如果某个字符已经被使用过set里已经存在就跳过。这也是我强烈建议你掌握“used数组路径记录”这种回溯写法的原因它的扩展性远好于交换法遇到重复字符的情况只需要加一行判断去重。void backtrack(vectorstring res, string cur, string s, vectorbool used) { if (cur.size() s.size()) { res.push_back(cur); return; } for (int i 0; i s.size(); i) { if (used[i]) continue; // 去重相同字符在同一层递归中仅使用一次 if (i 0 s[i] s[i-1] !used[i-1]) continue; used[i] true; cur.push_back(s[i]); backtrack(res, cur, s, used); cur.pop_back(); used[i] false; } }这段代码里的去重逻辑!used[i-1]很多人不理解为什么要判断前一个相同字符没被用过才跳过我解释一下当s[i-1]和s[i]相同如果s[i-1]还没被用说明当前轮次的排列一定会从s[i]开始这其实与从s[i-1]开始是完全重复的一个分支所以必须跳过如果s[i-1]已经被用了说明这次是在下层的递归里用到了s[i]这是合法推进不能跳过。这个细节如果不真正理解遇到变形题就判断失误。3. 实操演练从拿到题目到完美作答的完整过程3.1 拿到题后前5分钟到底该干什么我见过太多候选人拿到题目第一反应就是“这个题我见过我背过答案”然后直接开写。这是笔试中的大忌。正确的前5分钟应该是审题、确认边界、定复杂度目标。拿这套题里的“将字符串转换为整数”来说如果直接写一个循环累加你至少会漏掉三到五个面试官预设的测试点正负号处理、空字符串、数字溢出、空格开头、非法字符。我建议你在草稿纸上先列出这道题的所有边界情况再动手写代码这个过程本身就会给面试官留下“这个候选人有条理”的印象。以atoi为例正确审题后的状态应该是输入可能是空串返回0可能有前导空格需要跳过可能带正负号用flag标记数字中间如果混入非数字字符按C库函数行为是截断但面试时你要主动澄清需求数值可能溢出int范围需要用long long暂存并做溢出判断。我在给团队做Code Review时经常强调一句话“边界条件不是加分项而是及格线。”你连边界都没想清楚说明你对异常情况的敏感度不够这在线上系统里就是事故级别的问题。3.2 一道动态规划题从递归到备忘录再到递推的完整推导这套题里有一道经典动态规划题最长公共子序列LCS。很多刷题的人一看到DP就背状态转移方程但真正遇到笔试限时书写时容易出bug。我建议所有DP题都按这个流程走递归暴力解法 → 画递归树找重叠子问题 → 加备忘录 → 改写成递推。拿LCS来说暴力递归的定义是dp(i, j)表示text1[0..i-1]和text2[0..j-1]的最长公共子序列长度。状态转移如果text1[i-1] text2[j-1]则dp(i, j) dp(i-1, j-1) 1否则dp(i, j) max(dp(i-1, j), dp(i, j-1))。这个方程如果你直接从网上背下来很可能忽略一个细节——两个字符不相等时为什么是左边和上边的最大值而不是左上角加一因为公共子序列不要求连续text1减少一个字符或text2减少一个字符都可能保留更长的公共部分而dp(i-1, j-1)在这种情况下一定小于等于另外两个状态所以不用参与比较。写代码时可以用一个小技巧节省空间因为dp[i][j]只依赖dp[i-1][j]、dp[i][j-1]、dp[i-1][j-1]三格可以用一维数组加一个prev变量滚动更新。int longestCommonSubsequence(string text1, string text2) { int m text1.size(), n text2.size(); vectorint dp(n 1, 0); for (int i 1; i m; i) { int prev 0; // 相当于 dp[i-1][j-1] for (int j 1; j n; j) { int temp dp[j]; // dp[i-1][j] if (text1[i-1] text2[j-1]) { dp[j] prev 1; } else { dp[j] max(dp[j], dp[j-1]); } prev temp; } } return dp[n]; }在笔试时如果你能写出这个一维滚动数组版本并在注释里说明空间复杂度从O(m*n)降到了O(n)面试官通常会对你高看一眼。因为这说明你不仅理解DP还关注实际工程中大数据量下的资源消耗。3.3 代码做到什么程度才算“能交卷”很多人笔试时写得飞快但代码质量一塌糊涂。我结合阅卷经验总结了几条“交卷前必须自查”的标准变量命名是否自解释。不要用a、b、tmp这种名字用slow、fast、start、end这种一眼能看出含义的词是否有重复代码可以提取。比如判断链表节点合法性写了两遍就该考虑提前赋值给局部变量是否有注释说明关键逻辑。不需要每行都加注释但算法核心步骤、边界处理一定要注释是否测试过了自己列的边界用例。以快排分区函数为例至少要测[1,2]、[2,1]、[1,1,1]、空数组、单元素数组这五类输入。我在面试候选人时最反感的一种代码是跑了几个正常用例全过但数组为空或只有两个元素时直接崩溃。一问原因回答“我没想到这种情况”。笔试不是线上OJ不会只跑几个隐藏用例就放你走面试官会认真读你的代码找逻辑漏洞。所以“代码完整性”这个评分维度往往比“算法正确性”更能拉开差距。4. 从笔试到实战这些知识在工作里怎么用4.1 快排思想在业务排序引擎中的应用2016年那套题的快速排序题目我建议你不仅要会写递归版还要会写原地分区版和迭代版。因为在真实业务里比如一个订单系统需要按金额、时间、状态等多个维度排序底层虽然可能调用标准库的sort函数但sort的底层实现是内省排序快排堆排插入排序的混合理解快排的分区思想对优化大数据量排序有直接帮助。我之前优化过一个报表导出功能几百万行数据按指定列排序直接调用sort已经够快但在某些特殊分布下比如大量重复值sort内部会切换排序策略。当时我带着团队一步步用三路快排的思想改写了键值提取过程把多个维度的比较函数变成整数键的排序耗时从原来的8秒降到了1.5秒。这个优化思路说穿了就是那道题目里朴素快排在重复数据下退化问题的实战版。4.2 栈这个“不起眼”的数据结构撑起了函数调用和回退功能很多人在笔试里写了一堆栈相关的代码但没意识到栈在日常开发中的重要程度。函数调用栈、浏览器前进后退、IDE的撤销重做、表达式求值、括号匹配校验——全都是栈的应用。尤其是函数调用栈如果你不理解它你就无法真正理解递归为什么会溢出、为什么尾递归可以优化、为什么并发编程里的栈空间要单独分配。我举个具体场景排查生产环境的线程栈溢出问题。每次抛出StackOverflowError时你dump线程能看到一份完整的调用栈信息。这份信息能直接告诉你递归调用深到哪一层、是哪个条件没满足导致没有终止。如果你在校招笔试时已经把非递归遍历的栈模拟练得滚瓜烂熟你对这类排查会天然存在一种“肌肉记忆”知道栈顶、栈底、入栈、出栈这些动作是怎么具体发生的。这在排查复杂递归导致的问题时价值极高。4.3 哈希表的妙用不只是查找O(1)这套题里的哈希表题目考察的主要是理论复杂度但真实工程里哈希表在业务编码中的应用远比想象中多。我参与过的一个风控项目需要实时判断用户请求的频次最直接的办法就是用哈希表存每个用户最近一次的访问时间配合滑动窗口算法能在O(1)时间内完成频次判定。但这种方案存在哈希冲突和数据量膨胀的问题于是在细节上还需要设计扩容策略、淘汰策略。如果你在笔试阶段只记住了“哈希表查找O(1)”而没有想过负载因子、优雅扩容、哈希冲突链过长怎么办那么你在真实系统里大概率会被线上问题教育一遍。顺带说一个我在面试中经常追问的变体“如果内存有限不能一次性把几十亿条数据放进哈希表怎么办”这时候你要想到B树、Bloom Filter、LRU Cache等替代方案。2016年这套题虽然没考到这个深度但这个追问逻辑一脉相承从基础数据结构到工程资源约束下的方案选型。4.4 系统设计题里的算法痕迹这套笔试题主要考基础算法但大厂笔试/面试到了后期一定会涉及系统设计而系统设计里全是基础算法的影子。比如设计一个短网址服务核心是怎么生成不重复的短码——这可能是哈希、Base62编码、发号器三种方案各有取舍设计一个附近的人功能核心是GeoHash和空间索引设计一个消息队列核心是环形队列和读写指针的并发控制。我一直认为算法基础扎实的人系统设计能力不会差到哪去。因为系统设计的每一个环节你都能在基础数据结构里找到对应的影子。反过来如果一个人只会背系统设计模板分布式集群、一致性哈希说一套一套的但让他手写一个一致性哈希的“取模虚拟节点”实现完全写不出来这就是基础不牢的典型表现。5. 踩坑实录那些年我在笔试和真实项目里栽过的跟头5.1 排序题里“数组越界”的经典陷阱先说一个我在真实项目里栽过的跟头。有次做数据迁移需要把一批有序数据从旧库迁到新库为了保证主键不冲突新库里的自增ID从原最大值1开始。结果因为原库最大值统计时忽略了一种边界条件——表为空——加1之后变成1看起来没问题但数据校验时发现ID从2开始了。排查半天发现是原先的SQL取最大值时返回了NULL然后NULL加1还是NULL不是1。你还真别笑这种“理论上一行代码的事实际运行出现意料之外行为”的场景在笔试题目里是隐蔽的边界条件在真实项目里就是晚上十点的线上告警。所以我在笔试复盘时会把每道题的所有边界情况单独抄在一个本子上偶尔翻一翻。这种习惯帮我建立了极强的边界敏感度在后续带项目时少踩了很多坑。5.2 复杂度分析不能只背结论必须会算很多人说快排平均O(n log n)最坏O(n²)能背出来但一旦被问到“为什么平均是O(n log n)你是怎么理解这个代价的”就卡住了。我建议你在准备笔试时不仅要把结论记住还要亲手画出递归树分析每一层的合并开销和递归树的高度。拿归并排序举例每一层把所有子数组合并的总代价是O(n)递归树高度是log n所以总复杂度O(n log n)。快排与归并的区别是枢轴选的不好时递归树退化成单链高度变成n复杂度变为O(n²)。这个分析过程比背十遍“快排平均O(n log n)”都有用。因为它会在你遇到实际问题时自动引导你去思考“当前这个场景最坏情况会不会出现如果会我该怎么避免”。5.3 警惕“会写但不懂”的假掌握状态我辅导过不少候选人刷题量两三百道但在模拟面试时仍然容易被问倒。总结出一个共性他们处于一种“会写但不懂”的假掌握状态。一个题做完AC了就下一题从来不复盘为什么用这个算法、为什么这个时间复杂度的选择是合理的、还有没有更优解法。结果就是题库里见过的题能写出来题库里没见过的变形题直接崩溃。真正的“懂”有三个层次第一层能写出正确代码第二层能解释为什么这样做是对的第三层能说出这个方法的局限性和可能的优化方向。你在准备这套2016年腾讯笔试题时建议每个题都按照这三个层次进行自查尤其要盯住第三层。比如你做完链表的翻转能不能立刻说出递归和迭代两种版本各自的栈空间开销能不能说出如果链表很长递归法会不会爆栈这些才是面试官真正在意的深度。5.4 时间管理笔试不是做科研要学会取舍2016年这套题题量不小难度中等偏上。很多人在第一道算法题上死磕导致后面简单的题目没时间做这是最冤的失分方式。笔试从一开始就要有得分意识先把所有题目快速扫一遍标记出简单题、中等题、难题先把有把握的分数全部拿满再回头啃硬骨头。我个人的策略是前10分钟通读所有题目给每道题预估一个分数/时间比。比如一道20分的题预估要40分钟那说明性价比低先放着另一道15分的题预估10分钟能做完那就先做。这套方法在我的多次笔试和实际项目排期里都验证过有效——在资源有限的情况下先做优先级最高、成本最低的事永远是最优策略。6. 如何高效备战腾讯这类大厂算法笔试6.1 按知识点建立“错题本-思维链”而不是按题目建立错题本传统的错题本记录题目和答案效率太低。我建议你按知识点来组织笔记每个知识点下面回答五个固定问题问题模型是什么暴力解法是什么更优解法是什么复杂度的计算过程是什么这个题目在真实工程中的类比场景是什么举例针对“最长上升子序列”这个知识点问题模型给定一个数组找到最长严格递增的子序列长度暴力解法枚举所有子序列检验递增性复杂度O(2^n)更优解法贪心二分维护一个tails数组每遍历一个新数在tails中二分查找第一个大于等于它的位置并替换复杂度O(n log n)复杂度计算过程遍历n个数每个数一次二分检索O(log n)总复杂度O(n log n)工程类比在一个按时间排序的日志序列中统计某指标的最长连续上升趋势就可以借用这个思路。这五问一写下来你对一个知识点的掌握会扎实很多。复习时也是按知识点翻笔记而不是从第一道题翻到最后一道题。6.2 手写代码和IDE写代码完全是两种体验我强烈建议你在正式笔试/面试前用白纸或者最简单的文本编辑器做一些手写练习。因为现在很多线上笔试平台虽然提供代码高亮和自动补全但实际面试现场写代码时往往就是在共享白板/文档里手动敲。手写容易导致的低级错误包括漏分号、数组下标拼错、中英文括号混用、递归出口位置放错。这些错误在IDE里可能被编译器和自动补全纠正但手写环境下只能靠你自己的代码审阅能力。这里分享一个小技巧手写代码时先写函数签名和主逻辑框架把变量名和返回类型确定好再把细节填进去最后用自己预设的测试用例在纸面上模拟一遍执行。模拟执行时不要把精力放在“跑通”上而是放在“状态变化是否符合预期”上。对就是像CPU执行指令一样逐行走一遍这种训练对代码正确性的提升非常明显。6.3 善用“费曼技巧”检验自己是否真的懂了费曼技巧说白了就是如果你能把一个知识点用最通俗的语言讲给一个完全不懂的人听并且他能听懂那你才算是真的懂了。我在准备面试时经常在晚上把当天复习的算法题讲给一个非技术背景的朋友听。比如讲快排时我会说“就是把一堆数分成两堆小的站左边大的站右边然后每堆再重复这个过程直到每个数都在自己该在的位置。”这个过程看起来简单但实际操作时你会发现你讲不清“为什么遇到极端数据会变慢”讲不清“为什么三路快排能解决重复元素的问题”于是赶紧回去查资料补课。这种查漏补缺的效率比闷头刷题高得多。6.4 别忽视基础语言题C的底层细节是加分项2016年腾讯这套题里C相关的题目占了相当比例这也是腾讯作为老牌C大户的特色。我见过不少人把精力全放在算法题上语言题随便蒙结果总分被拉低。这里面的教训是语言基础题往往最容易拿分因为它考的是确定性的知识点不像算法题那样需要临场发挥。复习C时重点盯住几个方向指针和引用的区别、内存分配方式栈区、堆区、全局区、常量区、构造函数/析构函数/拷贝构造的调用时机、虚函数和动态绑定的实现原理、STL常用容器的底层结构。这些都是高频考点。我建议你花半天时间把《Effective C》的条款目录过一遍把每个条款标题翻译成“这是什么场景下的什么坑”然后对着目录能复述出具体内容就算过关了。7. 后续进阶方向从笔试到系统架构师的能力跨越如果你顺利通过了笔试和面试拿到了Offer接下来该怎么规划后续的技术成长这里我结合带团队和做技术分享的经验给你一条经过验证的进阶路径。第一步入职前三个月不要急着看业务代码先把公司内部的基础组件文档读完。了解公司用什么RPC框架、什么配置中心、什么监控系统、什么日志采集方案。技术栈可能不一样但底层思路你完全可以借鉴异步化、解耦、水平扩展、容灾降级。第二步第一个项目做完后主动复盘一次线上事故或性能优化。我建议每次复盘都写进自己的技术博客里不用发布就自己看半年后回头看你会发现自己对系统的理解会完全不同。很多人在面试时聊项目只会说“我用了什么框架、做了几个功能”这太浅了。有深度的人会说“我设计的方案为什么选这个存储、为什么用这个缓存淘汰策略、遭遇了什么问题、如何验证和灰度上线”这完全是两个层级。第三步向架构方向走的话一定绕不开《数据密集型应用系统设计》这本书。它讲分布式系统、存储引擎、一致性模型讲得远超一般系统设计面试题模板。读这本书时你会想起2016年笔试题里那些基础数据结构的影子跳表如何支撑Redis的有序集合B树如何支撑MySQL的索引LSM树如何支撑LevelDB的写优化。这些技术看起来都是“新东西”但底层的逻辑依然和你刷过的算法题一脉相承。我个人在做技术评审时有个习惯会追问方案设计者“你选这个方案它的最坏情况是什么怎么兜底”这个问题几乎可以套用到笔试中的任何一道算法题上也可以套用到任何一次线上设计评审上。技术选型没有银弹本质上都是在给定约束下的取舍谁掌握的基础信息越扎实谁做的取舍就越精准。最后说一个经验保持刷题的习惯不一定是为了面试当作日常“脑力健身”也很好。我自己每周会抽一两个小时按标签随机做两三道中等难度的算法题不让手生。技术这行很多人败在舒适区里止步不前。而那些持续保持学习状态的人往往十年后回头看发现自己已经甩开同龄人一段不小的距离了。