1. 题目
题目描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。
-
每种输入只会对应一个答案;
-
数组中同一个元素不能使用两遍;
-
返回下标顺序不限。
示例
输入:nums = 2,7,11,15, target = 9
输出:0,1
输入:nums = 3,2,4, target = 6
输出:1,2
约束
-
(2 <= nums.length <= 10^4)
-
(-10^9 <= numsi <= 10^9)
-
仅有一组有效解
2. 最佳解题思路描述(哈希表单次遍历,最优)
-
哈希表
unordered_map<int, int>:key 存数组数值,value 存对应下标; -
遍历每个元素,计算互补值
diff = target - nums[i]; -
若哈希表存在 diff,说明前面已出现匹配数字,直接返回
{mp[diff], i}; -
不存在则把当前数字与下标存入哈希;
-
先查询、后存入,天然规避同一元素重复使用。
优势
时间 (O(n)),仅遍历一次数组;空间 (O(n));大数据不会超时,面试标准写法。
3. 可优化代码(暴力双层循环,逻辑正确但性能差)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res ={};
for(int i=0;i<nums.size()-1;i++){
for(int j=i+1;j<nums.size();j++){
if(nums[i]+nums[j]==target){
res.push_back(i);
res.push_back(j);
return res;
}
}
}
return res;
}
};
代码说明
-
正确性:无逻辑 bug,所有测试用例均可通过;
-
缺陷与优化点:
-
时间复杂度 (O(n^2)),数组长度接近 1e4 时会超时;
-
外层循环条件
i < nums.size()-1没必要,直接i < nums.size()更通用; -
找到答案后可直接
return {i,j},无需先创建 vector 再 push,代码更简洁; -
多余初始化空 vector,最后无匹配返回用不到。
-
4. 两套标准代码
版本 1:优化后的暴力写法(仅适合学习,不推荐面试)
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (nums[i] + nums[j] == target) {
return {i, j};
}
}
}
return {};
}
};
版本 2:哈希最优解法(考场首选)
#include <unordered_map>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> mp;
int n = nums.size();
for (int i = 0; i < n; ++i) {
int diff = target - nums[i];
if (mp.count(diff)) {
return {mp[diff], i};
}
mp[nums[i]] = i;
}
return {};
}
};
5. 总结
-
双层暴力思路直观,但效率极低,数据量大直接超时;
-
哈希表是本题最优解,核心思路:用空间换时间,缓存已遍历数字;
-
关键顺序:先查差值,再存当前值,避免自身相加错误;
-
题目保证必有一组解,循环内找到可直接 return,无需走完整个数组。
6. 相关知识拓展
拓展 1:复杂度对比
-
双层循环:时间 (O(n^2)),空间 (O(1));
-
哈希单次遍历:时间 (O(n)),空间 (O(n))(最优)。
拓展 2:同类题型延伸
-
LC15 三数之和:排序 + 双指针去重,不能单纯哈希;
-
LC167 两数之和 II - 输入有序数组:双指针,无需哈希。
拓展 3:高频易错点
-
先存入当前数字再查询差值,出现自身配对错误(如 nums=3, target=6);
-
map 存储颠倒:把下标当 key、数值当 value,无法查找互补数;
-
暴力循环 i 与 j 边界写错,漏遍历组合或重复配对。