题目描述
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。
你可以按任意顺序返回答案。
示例 1:
输入: nums = [2,7,11,15], target = 9
输出: [0,1]
解释: 因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入: nums = [3,2,4], target = 6
输出: [1,2]
示例 3:
输入: nums = [3,3], target = 6
输出: [0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
思考
暴力解法是两重循环分别枚举数组中的两个数判断和是否为 target,显然这肯定不是这道题最佳解法。遍历每个数 nums[i] 的同时用哈希表记录 target - nums[i] 和 i,这样下次遍历到数值和 target - nums[i] 相同的数 nums[j] 就可以凑出一个 nums[i] + nums[j] = target,哈希表可以在 O(1)O(1)O(1) 时间内查找 nums[j] 同时返回对应的配对索引 i。这样就可以在一次遍历数组的情形下找出答案。
算法过程
- 初始化哈希表:用于存储“目标差值”与“索引”的映射(目标差值 = target - 当前元素值)。
- 遍历数组:
- 对每个元素
nums[i],检查哈希表中是否存在该元素(即是否有之前的元素满足“目标差值 = 当前元素值”)。 - 若存在,直接返回哈希表中记录的索引与当前索引
i。 - 若不存在,将“目标差值(target - nums[i])”和当前索引
i存入哈希表。
- 对每个元素
- 返回结果:因题目保证有唯一解,遍历过程中必然找到符合条件的两个索引并返回。
该过程通过哈希表将查找时间优化为 O(1)O(1)O(1),整体时间复杂度为 O(n)O(n)O(n),空间复杂度为 O(n)O(n)O(n)。
参考代码
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
if (map.has(nums[i])) {
return [map.get(nums[i]), i];
}
map.set(target - nums[i], i);
}
};
算法可视化

algorithm-visualizer 代码
// import visualization libraries {
const { Tracer, Array1DTracer, LogTracer, Layout, VerticalLayout } = require('algorithm-visualizer');
// }
// 输入参数
const nums = [3,2,4];
const target = 6;
// define tracer variables {
const arrayTracer = new Array1DTracer('数组');
const mapTracer = new Array1DTracer('哈希表(目标差值→索引)');
const logger = new LogTracer();
Layout.setRoot(new VerticalLayout([arrayTracer, mapTracer, logger]));
arrayTracer.set(nums);
mapTracer.set([]);
Tracer.delay();
// }
function twoSum(nums, target) {
const map = new Map();
let mapEntries = []; // 存储哈希表条目用于可视化
logger.println(`目标值: ${target},寻找和为目标值的两个元素索引`);
Tracer.delay();
for (let i = 0; i < nums.length; i++) {
// 高亮当前处理的数组元素
arrayTracer.select(i);
logger.println(`处理索引 ${i},元素值: ${nums[i]}`);
Tracer.delay();
// 检查哈希表中是否存在匹配的目标差值
if (map.has(nums[i])) {
const matchIndex = map.get(nums[i]);
// 高亮两个匹配的元素
arrayTracer.select(matchIndex, i);
logger.println(`找到匹配!索引 ${matchIndex}(值 ${nums[matchIndex]})和索引 ${i}(值 ${nums[i]})的和为 ${target}`);
Tracer.delay(1500);
return [matchIndex, i];
}
// 计算目标差值并存入哈希表
const complement = target - nums[i];
map.set(complement, i);
mapEntries.push(`${complement}→${i}`); // 用字符串表示键值对
mapTracer.set(mapEntries); // 更新哈希表可视化
logger.println(`存入哈希表:目标差值 ${complement} → 索引 ${i}`);
// 取消当前元素高亮(保持窗口移动效果)
arrayTracer.deselect(i);
Tracer.delay();
}
}
// 执行算法
twoSum(nums, target);
410

被折叠的 条评论
为什么被折叠?



