两数之和:从面试考察到算法实现
在算法面试中,“两数之和” 是一道出镜率极高的经典题目。它不仅是对基础编程能力的检验,更是大厂面试官筛选候选人的 “门面题”—— 通过这道题,面试官能快速判断应聘者是否真正理解算法思想,还是仅仅死记硬背热点考题。
面试中的考察核心
为什么 “两数之和” 会成为大厂面试的高频题?核心原因在于它能有效区分应聘者的算法素养:
- 基础掌握:能否写出可行解(暴力破解);
- 优化思维:能否从时间复杂度角度优化解法(空间换时间思想);
- 对数据结构的理解:是否熟悉哈希表等高效数据结构的应用。
面试官通过这道题,往往能刷掉那些只背题不理解原理的候选人,筛选出真正具备算法思维的人才。
解法一:暴力破解(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)。其核心思想是将 “求和” 转化为 “求差” :
-
遍历数组时,对于当前元素
nums[i],计算目标差值complement = target - nums[i]; -
检查哈希表中是否存在该差值:
- 若存在,直接返回差值对应的索引和当前索引
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) 空间存储哈希表,但在多数场景下,“空间换时间” 是更优的选择,也是面试官更希望看到的优化思路。