用 std::unordered_map 一次遍历可 o(n) 解决两数之和:对每个 nums[i],先查 target - nums[i] 是否已在表中,存在则返回二者下标,否则插入 nums[i] 及下标;须先查后插以防重复使用同一元素。

用 std::unordered_map 一次遍历解决,时间复杂度 O(n)
暴力双重循环(O(n²))在数组稍大时就明显卡顿,实际项目里基本不用。更优解是边遍历边查哈希表:对每个元素 nums[i],检查 target - nums[i] 是否已存在表中。存在则立即返回下标;不存在则把 nums[i] 和它的下标存入表。
注意点:
-
std::unordered_map查找平均 O(1),但最坏退化到 O(n),不过实际场景极少发生 - 必须先查后插——否则可能用同一个元素两次(比如
target = 6, 当前元素是3,表里已有3就会误判) - 返回的是下标而非数值,别漏掉存储索引
手写哈希表或排序 + 双指针?多数情况没必要
如果面试官明确禁用 STL 容器,才考虑替代方案。手写简易哈希表容易出边界错误,且 C++ 里没理由绕过 std::unordered_map。
双指针法需先排序,但会丢失原始下标——得额外维护索引映射,代码变长、易错,仅当内存极度受限且允许修改原数组时才考虑。
常见误操作:
- 排序后直接在新数组上双指针,却忘了同步更新下标映射 → 返回错误位置
- 用
std::map替代std::unordered_map→ 查找变成 O(log n),整体 O(n log n),无必要
LeetCode 测试用例常踩的坑
题目通常保证“有唯一解”,但实际编码仍要防御性处理:
- 输入为空或长度
-
target是负数或极大值 → 不影响算法逻辑,但确保用long long或检查溢出(尤其target - nums[i]可能溢出 int) - 数组含重复元素(如
[3,3],target=6)→ 哈希表插入时若 key 已存在,新下标会覆盖旧下标,但只要查的时候还没插当前项,就不会漏解
典型错误信息:reference binding to null pointer of type 'value_type',往往源于返回了未初始化的 vector 或空容器解引用。
一个安全可用的最小实现
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int int> seen;
for (int i = 0; i <p>真正容易被忽略的是:<code>seen[nums[i]] = i</code> 这句不能写成 <code>seen.insert({nums[i], i})</code> —— 后者遇到重复 key 会静默失败,导致后续查找失效。直接赋值才能确保最新下标生效。</p></int></int></int>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











