两数之和:从面试考察到算法实现

60 阅读3分钟

两数之和:从面试考察到算法实现

在算法面试中,“两数之和” 是一道出镜率极高的经典题目。它不仅是对基础编程能力的检验,更是大厂面试官筛选候选人的 “门面题”—— 通过这道题,面试官能快速判断应聘者是否真正理解算法思想,还是仅仅死记硬背热点考题。

面试中的考察核心

为什么 “两数之和” 会成为大厂面试的高频题?核心原因在于它能有效区分应聘者的算法素养:

  • 基础掌握:能否写出可行解(暴力破解);
  • 优化思维:能否从时间复杂度角度优化解法(空间换时间思想);
  • 对数据结构的理解:是否熟悉哈希表等高效数据结构的应用。

面试官通过这道题,往往能刷掉那些只背题不理解原理的候选人,筛选出真正具备算法思维的人才。

解法一:暴力破解(O (n²))

最直观的思路是暴力破解,通过双重循环遍历数组,检查每一对元素的和是否等于目标值。

其核心逻辑如下:

function twoSum(nums, target) {
  const len = nums.length;
  for (let i = 0; i < len; i++) {
    for (let j = i + 1; j < len; j++) {
      if (nums[i] + nums[j] === target) {
        return [i, j];
      }
    }
  }
}

这种解法的优点是思路简单、容易实现,但时间复杂度为 O (n²)(n 为数组长度)。当数组规模较大时,双重循环会导致运算效率急剧下降,因此在面试中,暴力解法通常只能作为 “保底解”,难以满足面试官对优化能力的考察要求。

解法二:哈希表(O (n))

更优的解法是利用哈希表的特性,通过 “空间换时间” 将时间复杂度优化至 O (n)。其核心思想是将 “求和” 转化为 “求差”

  1. 遍历数组时,对于当前元素nums[i],计算目标差值complement = target - nums[i]

  2. 检查哈希表中是否存在该差值:

    • 若存在,直接返回差值对应的索引和当前索引i
    • 若不存在,将当前元素nums[i]及其索引i存入哈希表,继续遍历。

基于对象的实现(ES5 及以上)

在 JavaScript 中,对象可以作为简易哈希表使用,通过键值对存储元素与索引的映射:

function twoSum(nums, target) {
  const diffs = {}; // 存储已遍历元素:{元素值: 索引}
  const len = nums.length;
  for (let i = 0; i < len; i++) {
    const complement = target - nums[i];
    if (diffs[complement] !== undefined) { // 检查差值是否存在
      return [diffs[complement], i];
    }
    diffs[nums[i]] = i; // 存入当前元素及索引
  }
}

基于 Map 的实现(ES6 及以上)

ES6 提供的Map结构是更专业的哈希表实现,支持更规范的键值对操作:

function twoSum(nums, target) {
  const diffs = new Map(); // 存储已遍历元素:key为元素值,value为索引
  const len = nums.length;
  for (let i = 0; i < len; i++) {
    const complement = target - nums[i];
    if (diffs.has(complement)) { // 检查差值是否存在
      return [diffs.get(complement), i];
    }
    diffs.set(nums[i], i); // 存入当前元素及索引
  }
}

哈希表解法的优势

相比暴力破解,哈希表解法的时间复杂度从 O (n²) 降至 O (n)(只需一次遍历),极大提升了效率。这得益于哈希表的查找操作(diffs[complement]diffs.has(complement))的时间复杂度为 O (1)。

代价是需要额外的 O (n) 空间存储哈希表,但在多数场景下,“空间换时间” 是更优的选择,也是面试官更希望看到的优化思路。