技术面试准备实战——不只是刷题,我认为更重要的是这些
技术面试准备实战——不只是刷题,我认为更重要的是这些
适读人群:正在准备或即将准备技术面试的工程师 | 阅读时长:约19分钟 | 核心价值:一套面试准备的完整方法论,刷题只是其中一小部分
先说一个让人不舒服的事实:大多数人准备面试的方式,是低效的。
他们花了大量时间刷 LeetCode,刷到第300道题的时候,发现面试里考到的题目只有两道是做过的,而且真正让面试失败的,不是算法题,而是被追问"你们系统的并发量是多少,怎么解决高并发下的库存超卖"的时候,说不出来。
我参与过两侧:被面试的一侧,和面试别人的一侧。我自己面试过大概7家公司(成功进了其中4家),也面试过大概40-50个候选人。
从两侧的视角,我想讲讲,准备面试,什么是真正重要的。
先说一个不受欢迎的观点:LeetCode 刷多少够用
很多人会问:"LeetCode 要刷多少道才够?"
我的回答:这个问题本身就问错了。
问题应该是:你面试的公司,对算法的考察深度是多少?
不同公司对算法的要求差异极大。
一线大厂(Google、字节、美团):算法是筛选的重要维度,中等难度题要能流畅解决,Hard 题会出现。刷题数量通常需要200道以上,而且要深度理解,不是背答案。
中等规模的技术公司:算法会考,但不是最重要的维度,通常在简单到中等难度之间,更关注你的系统设计和实际项目经验。
传统行业的技术岗位:算法可能只是走个过场,更关注你做过什么、能不能快速上手业务。
你刷题的量和深度,要匹配你目标公司的要求,而不是追求一个绝对数字。
在算法没问题的前提下,以下这些东西,对面试成败的影响,往往比刷多100道题更大。
第一大块:讲清楚你做过的项目
这是面试中最被低估的环节,也是区别好候选人和普通候选人的最关键地方。
面试官问"介绍一下你做过的最复杂的项目",这个问题的难点不在于"你做了什么",而在于"你能不能讲清楚,你做了什么,为什么这样做,有什么挑战,你是怎么解决的"。
很多工程师在讲项目的时候,只说了"做了什么",没有说"为什么这样做"和"有什么挑战"。这让面试官没办法判断:这个人是真的理解了这个系统的设计取舍,还是只是按别人的方案执行的?
准备项目介绍的结构(STAR 变体):
- 背景:项目是什么,解决什么问题,业务规模(数据量、用户量、QPS)
- 你的角色:你在这个项目里负责什么,团队规模
- 核心挑战:这个项目里最难的技术问题是什么
- 你的方案:你怎么解决的,考虑了哪些选项,为什么选了这个
- 结果:实际效果如何,有什么可以改进的
重点在第3和第4点。没有说清楚"挑战和解决方案"的项目介绍,是没有分量的。
做一件事:把你最重要的两三个项目,用上面的结构,写成文字,然后口头练习讲给别人听,听他们能不能理解。
这个练习,比刷10道 LeetCode 有用得多。
第二大块:系统设计
对于有2年以上工作经验的工程师,系统设计通常是面试的重要环节,有时候权重甚至超过算法题。
系统设计题通常是开放式的:设计一个秒杀系统、设计一个消息通知系统、设计一个分布式限流器……
这类题没有标准答案,考察的是:你是否理解系统设计的取舍,能不能在约束条件下做出合理的决策。
系统设计的通用框架:
- 澄清需求和约束:先问清楚规模(日活多少、QPS 多少、数据量级),再问功能范围(哪些功能在设计范围内,哪些不是)
- 估算规模:基于上面的信息,做一个粗糙的容量估算
- 高层设计:先画出系统的大致架构,讲清楚主要组件
- 核心组件深入:挑出最核心或者最有挑战的组件,展开讲
- 识别和处理瓶颈:主动说出这个设计的瓶颈在哪里,如何扩展
注意第5点特别重要:主动说出设计的缺陷,比被面试官挖出来强。说明你有全局思维,能看到自己设计的边界。
系统设计的准备方法:
多读真实的技术架构文章(各大厂的技术博客、InfoQ 等),理解真实系统是怎么设计的,背后的取舍是什么。然后对每个系统,练习能不能复述出来这套设计的核心思路。
推荐练习题:设计 URL 短链服务、设计微博的 Feed 流、设计秒杀系统、设计一个消息队列。
第三大块:Java 底层知识和技术深度
对于 Java 工程师,面试通常会考察 JVM、并发、集合框架等底层知识。
不是为了考察你背书的能力,而是通过这类问题判断:你对你用的工具,是真的理解了,还是只是会用。
这类知识的准备,不能靠临时背八股文。背下来的八股文,面试官追问一两个问题就穿帮了。
有效的准备方法是:对每个技术点,要能回答三个问题:
- 它是什么(基本定义)
- 它解决了什么问题(为什么存在)
- 它有什么代价/局限(tradeoff)
比如对于 ConcurrentHashMap:
- 它是什么:线程安全的 HashMap 实现
- 它解决了什么问题:多线程场景下的并发读写
- 它的代价:在并发写入时,仍然会有分段锁竞争,在极高并发下还是有性能上限
能这样三维度说清楚一个技术点,才是真正理解了,而不是背了一个定义。
第四大块:行为面试和软技能
很多技术面试里会有行为面试(Behavioral Interview),这是很多工程师最没准备的一块,却往往影响最终的 Offer 决定。
常见的行为面试问题:
- 讲一个你在团队里遇到的技术争议,你是怎么处理的
- 讲一次你的决策后来被证明是错误的,你做了什么
- 讲一次你在很短的时间内学习了一个新技术并应用的经历
这类问题的准备方法:提前准备3-5个可以套用的真实故事,每个故事覆盖不同的方面(冲突处理、从错误中学习、技术挑战等)。
讲这类故事的时候,要有数字、有细节、有你自己的判断和反思,不要只描述"我做了什么",要说清楚"为什么这样做"、"结果是什么"、"我学到了什么"。
第五大块:面试中的沟通
这是另一个被严重低估的维度。
面试考察的不只是你知道多少,还考察"和你合作,会是什么体验"。
一个很聪明但沟通方式让人不舒服的候选人(比如:态度傲慢,遇到不会的问题直接说"这个题没意义",或者拒绝接受提示),通常拿不到 Offer。
几个沟通上的建议:
遇到不会的问题,诚实说,然后尝试:"这个我没有做过,但我来想一下……",然后展示你的思考过程。面试官通常更想看到思考过程,而不是最终答案。
主动展示思考而不是沉默:面试题做的时候,把你的想法说出来,哪怕只是"我在想先处理边界 case"或者"我先想到的是暴力解法"。沉默解题让面试官很难了解你。
有异议时,礼貌表达:如果面试官给了一个你不同意的提示,可以礼貌地说"我理解你的建议,不过我在想这个方案在XXX情况下可能有问题,我想先试试另一个方向,你觉得可以吗?"
一个真实的面试复盘
我印象最深的一次失败面试:面试一家公司的高级工程师岗位,技术部分答得还不错,但在最后的"你有什么问题要问我们"环节,我问了一个很表面的问题("团队规模是多少"),而不是问一些能展示我对这个岗位有认真思考的问题。
结束后面试官给 HR 的反馈是:技术能力够,但对这个岗位的热情和深入思考没有表现出来。
后来我改变了策略,在面试前,针对这家公司,认真研究他们的技术博客、GitHub、招聘 JD,准备3-5个有质量的问题。这些问题本身就是一种展示——"我认真研究了你们,我有具体的问题"。
这一个改变,让我后来的面试通过率明显提高。
面试后的跟进
面试结束之后,很多人的操作是:等消息。
更好的操作是:在24小时内,发一封简短的感谢邮件给面试官或者 HR,说一句"感谢今天的面试,我在讨论XXX问题时受到了启发,期待有机会进一步交流"。
这件事听起来有点虚,但它确实有效:
- 让面试官对你有更好的印象(大多数候选人不做这件事)
- 如果你在某个问题上的回答不够好,这个邮件可以补充一点你的想法
- 建立起一个基本的沟通关系,即使这次没有机会,未来也可能有
面试本身是一个可以学习的技能
最后说一个认知:面试是一个技能,和写代码一样,需要练习才能提升。
第一次面试通常很糟糕,第十次会比第一次好很多,不是因为你技术水平提升了,而是因为你知道怎么表达自己了。
所以,不要等到"找工作的时候"才开始面试。平时接到猎头或者公司的面试邀约,可以有选择地参加一些,练习面试的感觉,了解市场上对工程师的要求,顺便让自己保持对外部机会的感知。
这种状态下的面试,没有压力,反而能发挥得更好,也更容易收获真实的反馈。
关于"八股文"的正确态度
最后说一下八股文。
很多工程师对八股文有两种极端态度:要么"背就对了",要么"这东西完全没用,考这个的公司不值得去"。
我的观点是:八股文里的知识点本身是有价值的,只是死记硬背的学习方式没有价值。
理解 JVM 内存模型、理解并发控制、理解数据库事务,这些都是工程师应该掌握的知识。如果你是通过"理解了再记忆"的方式学的,那你在面试中被追问的时候能答出来,工作中遇到相关问题时也能用上,这是真正的学习。
但如果你只是机械背诵,面试时背完了,工作中遇到实际问题还是不会,那这种准备只有短期效果,没有长期价值。
把面试准备变成真正的学习机会,而不只是通关任务。
