题目:
提示:
给定一个整数数组 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- 只会存在一个有效答案
解题分析:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 给定 nums = [2, 7, 11, 15], target = 9。因为 nums[0] + nums[1] = 2 + 7 = 9。所以返回 [0, 1] 思路 最简单的方法是通过两层for循环进行遍历, 使用暴力的查找两个子元素。但是这种方法的时间复杂度为O(n^2)。在大数据量的测试用例的情况下执行时间超时。那么我们有什么办法可以将时间复杂度降下来吗?这时我们可以用到HashMap。通过HashMap我们可以将时间复杂度降为O(2n)。如果是有序数组的情况下, 时间复杂度可以是O(n), 详见下方代码:
1、使用map
这个思路比较简单,而且复杂度低,但是需要对map有对应的应用和理解;
通过这个方法,我学习到的一点是:数组中的某一项和这一项的下标用map对应起来。通过map的key、value把数组中的值和它对应的下标很巧妙的结合起来,是一个很好的思路。
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
let [res,len,map] = [[],nums.length,new Map()];
for(let i = 0; i < len; i++){
let diff = target - nums[i];
if(map.has(diff)){ // 如果map中存在这个数,则获取对应的这个数的数组下标;
res.push(i,map.get(diff))
return res;
}else{
// 对应的数组中的某个数和数字下标用map对应起来。通过map的key、value把数组中的值和它对应的下标对应起来。
map.set(nums[i],i)
}
}
return res;
};
2、使用两个for循环
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
let len = nums.length;
// 使用两个for循环是我们大多数时候能想起来的思路,但是性能不如map好
for(let i = 0; i < len; i++){
for(let j = i+1; j < len; j++){
if(nums[i]+nums[j] === target){
return [i,j]
}
}
}
return []
};
3、先记录下标,然后对数组进行排序,使用双指针法(这个方法比较复杂,是借鉴的三数之和的方法)
var twoSum = function (nums, target) {
let [res, arr, len] = [[], [], nums.length];
// 把数组的每一项和它的下标记录下来,放在数组中
nums.forEach((item, index) => {
arr.push({ key: index, value: item })
})
// 对数组进行排序
arr.sort((a, b) => a.value - b.value)
for (let i = 0; i < len - 1; i++) {
let k = len - 1
while (i < k) {
let sum = arr[i].value + arr[k].value
if (sum < target) {
i++
// 对重复数字进行处理
if (i > 0 && arr[i - 1].value === arr[i].value) {
i++
}
} else if (sum > target) {
k--
// 对重复数字进行处理
if (k > 0 && arr[k + 1].value === arr[k].value) {
k--
}
} else {
// 输出下标
res.push(arr[i].key, arr[k].key)
return res
}
}
}
return res;
};