Sunday面试指南

两数之和怎么用哈希表实现?为什么要先查再存,不能重复使用同一个元素?

下面是一段教学用的模拟面试。

🧑‍💻 面试官: 两数之和怎样从两层循环优化?

🙋‍♂️ 我: 用哈希表,把数放进去,查另一个数是否存在。

🧑‍💻 面试官: 输入只有一个 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;
}

输入按题意使用整数;TS 的数值范围还应限制在能够精确表达这些运算的范围内。这里找一组下标,没有答案返回 null、None。题意参照 LeetCode Two Sum。

两个3可以,一个3不行

图:两个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 的独立解析。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历