手撕代码与算法面试:常见形式、典型题型和如何出声解题

· · 8 分钟阅读

“手撕代码”指面试中不借助 IDE 自动补全、现场手写代码解题,常见形式是共享在线编辑器、白板或纸面。多数面试官看的不只是“做出来没有”,更看你的思路、沟通和对边界的处理。所以准备时要同时练两件事:把题做对,以及边写边把思路说出来。具体的题型、时长和难度各公司、各岗位差别很大,本文不对任何公司的流程作断言,以下内容是通用的练习方法,题目与对话均为示意。

手撕代码常见的形式

  • 在线协同编辑器。面试官和你同时看到一个代码区,可能能运行也可能不能运行。
  • 白板或纸面。多见于线下面试,重点在思路和代码结构,小语法错误通常容忍度较高。
  • 先说思路再写。很多面试官会要求先讲思路,确认方向后再动手。
  • 从基础题延伸到手写实现。例如手写 LRU、单例、防抖节流、线程池、快速排序、二分查找等。

具体是哪一种,面试前问一下招聘方最稳妥,也可以问是否能运行代码、可以用哪种语言。线上笔试平台的形式可参考《华为 OD 机考指南》和《牛客、北森在线测评的监考方式》。

常见题型清单

下面是技术面试里长期出现的题型类别,用来列练习清单,而不是预测某家公司的真题:

  • 数组与字符串:双指针、滑动窗口、前缀和(两数之和、最长无重复子串、合并区间)。
  • 链表:反转、判环、合并有序链表、删除倒数第 N 个节点。
  • 树与图:层序遍历、二叉树最近公共祖先、岛屿数量、拓扑排序。
  • 栈、队列、堆:有效括号、单调栈、前 K 个高频元素、数据流中位数。
  • 动态规划与回溯:爬楼梯、背包、最长公共子序列、全排列、子集。
  • 手写实现类:LRU 缓存、生产者消费者、限流器、简单的线程池、Promise 相关实现(前端岗)。

如果你想了解真实面试里 LeetCode 式题目的比重和风格,可以读《真实面试里的 LeetCode》。

边写边说:一个五步流程

  1. 复述题目并确认。“题目是给一个整数数组,找出两个数之和等于目标值,对吗?数组有序吗?有没有重复元素?”
  2. 先说暴力解。“最直接是双重循环,时间 O(n²),空间 O(1)。”先有一个能工作的方案,心理压力会小很多。
  3. 再说优化思路。“可以用哈希表记录已经遍历过的数,每次查目标值减当前值是否存在,时间 O(n),空间 O(n)。”
  4. 动手写,同时轻声解说。不要一言不发地写十分钟,也不用逐字念代码,说关键决定即可:“这里我先判断空数组。”
  5. 用例子走一遍。拿一个小样例手动执行,再试空输入、单元素、重复元素等边界情况,最后分析复杂度。

示例:说出思考,而不是沉默

下面是示意对话,题目是“合并两个有序链表”。

你:我先确认一下,两个链表都是升序,返回合并后的升序链表,对吗?可以新建节点,还是要原地合并?
面试官:都可以。
你:那我用原地合并,节省空间。思路是用一个哑节点做头,两个指针分别指向两个链表,每次接较小的那个,最后把剩下的一段直接接上。时间 O(m+n),空间 O(1)。我开始写。
(写到一半)你:这里我用哑节点是为了避免单独处理头节点为空的情况。
(写完后)你:我用 [1,2,4] 和 [1,3,4] 走一遍……再看一下其中一个为空的情况,应该直接返回另一个。

这样的表达让面试官即使看到你有小 bug,也能判断你的思路是对的。

卡住了怎么办

  • 说出你卡在哪。“我现在在想怎么避免重复计算。”面试官可能给提示,这并不丢人。
  • 退回简单情形。先解小规模或特殊情况,再推广。
  • 先写暴力解保底。一个正确但慢的解,好过没有解。写完后说“我知道它不够好,让我想想怎么优化”。
  • 接受提示后复述。“您的意思是可以用单调栈,我理解一下……”这展示了沟通能力。
  • 语言熟练度。选你最熟的语言,不要为了显得专业而换用不熟的。

怎么练:与刷题不同的三点

  1. 限时 + 不看答案。每题限定 20–30 分钟,超时再看题解,并记录卡住的原因。
  2. 出声练习。对着空气或录音讲思路,练到不再沉默为止。
  3. 脱离 IDE 写代码。在纯文本编辑器或纸上写,练习不依赖自动补全和运行结果。

系统性的准备清单见《技术面试准备》,实时写代码时的沟通技巧可参考《实时编程面试指南》。

容易丢分的细节

  • 忽略边界。空数组、单元素、整数溢出、重复值、负数,是最常被追问的地方。写完后主动检查,比被问到再改印象好得多。
  • 变量命名随意。手写时 a、b、c 很容易自己都看乱,用有含义的名字,如 left、right、window。
  • 不说复杂度。写完主动给出时间和空间复杂度,并说明还能不能优化。
  • 一开始就追求最优解。想不出最优解时,先交出可用的方案,再迭代。
  • 不验证。没有运行环境时,更要用小样例手动执行一遍,抓住自己的低级错误。
  • 手写实现类题目只会背模板。例如 LRU,要能解释为什么用哈希表加双向链表,每个操作的复杂度是多少,以及并发场景需要注意什么。

实例拆解:手写 LRU 缓存

LRU(最近最少使用)几乎是手撕环节的“常客”类别之一。要求通常是:get(key) 和 put(key, value) 都是 O(1),容量满时淘汰最久没被使用的项。

  • 经典做法:哈希表加双向链表。哈希表按 key 找到链表节点,链表头部表示最近使用,尾部表示最久未使用;访问时把节点移到头部,淘汰时删尾部。要说清楚为什么用双向链表:删除任意节点需要 O(1) 找到前驱。
  • 语言自带的捷径:Python 的 collections.OrderedDict 提供 move_to_end 和 popitem,官方文档明确提到它适合实现各种 LRU 缓存;popitem(last=False) 按先进先出顺序弹出最旧的项。但面试官未必接受直接调库,建议先问“可以使用标准库的有序字典吗”,得到允许再用,并仍然能讲出底层原理。
  • 你要主动补充的边界:容量为 0 或 1、对已存在的 key 做 put 要更新并移到头部、get 不存在的 key 的返回约定。
  • 常被追问:多线程下怎么办?(加锁,或分段)如何支持过期时间?如何做成分布式?不必一次答全,先答你确定的部分。

一段示意:用问题澄清代替猜测

题目:“实现一个函数,判断字符串中的括号是否有效。”(示意)

你:“字符串里只包含圆括号、方括号、花括号三种,对吗?空字符串算有效吗?”
面试官:“只有这三种,空串算有效。”
你:“我想用栈:遇到左括号入栈,遇到右括号就检查栈顶是否匹配,最后栈为空才有效。时间 O(n),空间最坏 O(n)。”
你(写完后):“边界我再看一遍:奇数长度一定无效,所以可以提前返回;栈空时遇到右括号,要返回 false,不能弹栈。”

你会发现,这个流程里大部分得分点来自“澄清”和“验证”,而不是代码本身。

关于辅助工具与规则

Interview Copilot 是一个桌面悬浮窗,可以识别通话声音、提供提示,也能对代码题截图进行讲解,并有无需绑卡的免费方案可先试用。它很适合用于赛前练习:对着题目讲思路,再对比提示补漏洞,详见AI 编程面试助手。

在正式的面试或笔试中能否使用任何辅助工具,完全由公司和平台的规定决定。部分笔试平台会进行监考或记录,违反规则可能导致成绩作废。请在面试前直接向招聘方确认是否允许,并按对方的要求执行。我们不提供也不建议任何绕过规则的做法。

参考来源

以上页面于 2026 年 11 月 13 日打开核对。文中对面试形式与题型的描述为通用经验总结,不代表任何公司或平台的官方说法;请以招聘方通知和平台规则为准。

FAQ

手撕代码是什么意思?

指面试时不依赖 IDE 的自动补全和调试功能,在白板、纸面或在线编辑器里现场手写代码解题。面试官关注的是思路、代码正确性、边界处理和沟通,而不只是最终是否通过。

手撕代码面试一般考哪些题?

常见类别包括数组与字符串、链表、树与图、栈队列堆、动态规划与回溯,以及 LRU、线程池、限流器等手写实现类题目。具体题目因公司和岗位而异,可按类别建立练习清单,而不是押题。

手撕代码时需要一边写一边讲吗?

通常建议这样做。先复述题目并确认条件,再讲暴力解和优化思路,写代码时解说关键决定,最后用样例走一遍。沉默地写完整段代码,面试官很难判断你的思路。

手撕代码时卡住了怎么办?

说出你卡在哪里,退回简单情形,先写一个正确但较慢的暴力解保底,再讨论优化。接受提示后用自己的话复述,展示沟通能力。不要长时间沉默。

手撕代码应该用什么语言?

用你最熟练的语言,除非岗位或面试官明确指定。语言熟练意味着能把精力放在算法本身,而不是语法细节。面试前可以问清是否有语言限制。

怎么练习手撕代码效果最好?

限时、不看答案、出声讲解、脱离 IDE 手写,四点结合。每题限定 20–30 分钟,超时后看题解并记录卡住的原因,之后隔几天重做一遍同类题。

面试或笔试中可以使用 AI 辅助吗?

由公司和平台的规则决定,各家不同且会变化。有些平台会监考或记录行为。请在面试前向招聘方直接确认是否允许,并严格遵守。违规可能导致成绩作废或取消资格。

应用在这里如何帮忙

相关文章

继续阅读