两数之和怎么用哈希表实现?为什么要先查再存,不能重复使用同一个元素?
下面是一段教学用的模拟面试。
🧑💻 面试官: 两数之和怎样从两层循环优化?
🙋♂️ 我: 用哈希表,把数放进去,查另一个数是否存在。
🧑💻 面试官: 输入只有一个 3,目标是 6。你先把 3 存进去再查,会不会把自己用两遍?
🙋♂️ 我: 应该先查询补数,再保存当前数。
🧑💻 面试官: 输入是两个 3 呢?负数和重复值会破坏这个思路吗?
哈希表不只是为了快,还要配合「先查后存」,保证找到的是之前那个位置,而不是当前元素自己。
面试速答(60 秒版)
遍历数组时,当前数为 x,就查询哈希表中是否已有 target-x。如果有,返回那个已有位置和当前位置;如果没有,再把 x 与它的下标保存下来。
哈希表保存的是已经经过的元素,所以两个下标不会相同。两个值都为 3、目标 6 也能正确处理:第二个 3 查询时,第一个已经存在。
在哈希操作平均常数时间的通常假设下,总时间 O(n),额外空间 O(n)。这是复杂度模型,不是无条件的最坏时间保证。
还要说清返回下标还是数值、找一个答案还是全部答案,以及没有答案怎么表示。需求改变,代码也要调整。

图:两数之和,先查再存。
知识点详解:我们要找的是当前数缺少的那一半
两层循环为什么多做了工作?
假设数组是 2、7、11、15,目标是 9。暴力方式会反复枚举数对,判断它们相加是否等于目标。
但看到 7 时,其实只需要问:“之前有没有 2?”哈希表帮助把查找这个补数的过程缩短,而不是继续与全部旧元素逐个相加。
顺序怎样保证不同下标?
看到第一个元素时,表还是空的。只有没找到答案,才把它存进去。
看到后续元素时,表中的记录全部来自之前位置。这样,即使补数等于当前数,也不会用当前元素自身凑答案。
function twoSum(nums: readonly number[], target: number):
[number, number] | null {
const seen = new Map<number, number>();
for (let i = 0; i < nums.length; i++) {
const other = seen.get(target - nums[i]);
if (other !== undefined) return [other, i];
seen.set(nums[i], i);
}
return null;
}def two_sum(nums, target):
seen = {}
for i, value in enumerate(nums):
other = target - value
if other in seen:
return [seen[other], i]
seen[value] = i
return None输入按题意使用整数;TS 的数值范围还应限制在能够精确表达这些运算的范围内。这里找一组下标,没有答案返回 null、None。题意参照 LeetCode Two Sum。

图:两个3可以,一个3不行。
重复值为什么不用额外特殊处理?
输入 3、3,目标 6。第一个 3 没找到补数,保存下标 0;第二个 3 查到它,返回 0、1。
如果某个值多次出现,示例可能用较新的旧下标覆盖较早下标,但寻找一组合法答案仍然成立。如果要求所有组合,或者要求特定的下标顺序,就不能继续只保存一个下标。
负数也一样,补数仍然由 target-x 计算。它们不会让这份查找规则失效。
排序双指针为什么不是同样的回答?
排序后可以用双指针调整两端,但原题要求原下标。排序若丢掉位置,就只得到了值,不是题目要求的答案。
可以携带原下标排序,但会引入排序成本。选择方案时,先看输出和空间要求,而不是觉得“双指针听起来更高级”。
复杂度要带上假设
哈希表查询和写入通常按平均 O(1) 分析,遍历 n 次得到平均 O(n)。
额外存储最坏可能接近 n 个值。用空间换查找成本是这道题的主要取舍,不能因为只有一张表就说空间 O(1)。
面试官继续追问
为什么不能判断 if (other)?
下标 0 也是真实答案,在 JS 里却是假值。要检查“是否存在”,不能检查下标是否为真值。
题目换成全部答案怎么办?
要定义是否按值去重、允许多少组合,并保存足够的下标信息。输出本身可能很大,不能沿用“最多一组”的复杂度表述。
面试速记卡
- 查找:当前数 x,找 target-x。
- 顺序:先查询,再保存当前元素。
- 身份:返回两个不同下标,不复用当前元素。
- 成本:平均 O(n) 时间,O(n) 额外空间。
- 边界:下标 0、重复值、无解与数值范围。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
字节跳动 · 前端 · 实习
怎样用线性时间求两数之和?(题意整理)
字节跳动飞书多维表格实习面经(三面挂) ↗
原帖发布于 2025-05-26