题目:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例:
示例一:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例二:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例三:
输入:nums = [3,3], target = 6
输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?
思路
阅读题目,这个问题可以用:在整数数组中,找出和为给定整数值的两个整数的下标。
关键是两个数,这两个数的和是给定的,而且这个和的加数只能在给定的数组里面。所以,基于给定的和,对于数组里的每一个整数,另外一个满足条件的被加数都是确定的,如果这个被加数在数组中,获取被加数的下标以及当前加数的下标,就可以返回答案了。
关键在于如何在数组中找到这个被加数,对于数组中的每一个整数而言,这个问题就变成了,如何在整数数组中找到一个特定的整数,这样就是一个比较简单的问题了。
我们可以从头到尾遍历一遍这个数组,直到找到目标整数或者遍历到末尾。但是这样对于大规模的数组是十分费时的。为了满足时间限制,我们可以想到用空间换取时间的方法——哈希表。
我们可以把数组中的所有整数都作为键加入哈希表中,并且以每个整数的下标作为值,利用这个数据结构的特点,我们可以在 O(1) 的时间内找到一个特定整数所在的下标。然后我们再遍历一遍数组,查找对于每个整数其满足条件的另一个整数的下标。
将所有的整数存入哈希表需要遍历一次数组,对每个整数在哈希表中查找对应的被加数也要遍历一次数组。根据题目的条件,顺序不是重要的,我们可以通过 a 找到 b,也可以通过 b 找到 a,在一开始哈希表是空的,如果先遍历到 a,虽然 a 不能在哈希表中找到它对应的被加数 b,但是当遍历到 b 时,a 已经在哈希表中了,所以我们就可以直接查找到 b,而这个结论对于 a b 在数组中的先后位置反过来的情况依然成立,所以我们可以将循环减少到一次。
代码
function twoSum(nums: number[], target: number): number[] {
const map = new Map<number,number>() // key:整数值,value下标
for (let i = 0; i < nums.length; i++) {
const curNum = nums[i]
const matchedNum = target - curNum;
if (map.has(matchedNum)) {
return [i, map.get(matchedNum)]
} else {
map.set(curNum, i)
}
}
return [];
};