「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
题目
给定一个整数数组 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
只会存在一个有效答案
进阶:
你可以想出一个时间复杂度小于 O(n2) 的算法吗?
解题思路
拿到这道题,我首先想到的是通过for循环来遍历数组,分别拿到arr[i]和arr[j]的值来判断相加是否为target目标值。
【方法一:for循环暴力破解】
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
for(let i = 0; i < nums.length; i++) {
for(let j = i+1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) {
return [i, j];
}
}
}
return [];
};
但是熟悉时间复杂度的同学应该会知道,当我们使用for循环嵌套的时候,时间复杂度其实是n的嵌套次数次方。即当前方法下的时间负责度为O(N2)。
这种方法虽然浪费了时间复杂度,但没有新建任何多余的空间去存放数据,因此,空间复杂度为O(1);
总结:
- 时间复杂度:O(N2)
- 空间复杂度:O(1)
通过题目的提示我们可以得知应该会有更好的解决时间复杂度过高的方法
或者我们可以牺牲空间换取时间呢?
ES6中我们曾经学习过MAP集合,可以存储key-value的键值对(也就是我们所说的hash结构)
可以通过 new MAP() 来获取一个map实例
map实例所拥有的属性和方法:
- size属性:可以获取map实例的总成员数(长度)
- set方法:
set(key, value)设置key对应的键值,如果key已有值,则会更新 - get方法:
get(key)读取对应key的值,如果没有则返回undefined - has方法:
has(key)判断这个key是否存在MAP结构中,返回布尔值 - delete方法:
delete(key)删除某个key,如果有/删除成功返回true,否则返回false - clear方法:
clear()清除MAP中所有成员
因此,我们可以通过创建一个新的MAP空间,存放对应的需要的值,再根据MAP的set和get方法相应的去添加或获取某个值来解决问题。
【方法二:MAP集合/hash结构】
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
\\ 新建一个map实例
let map = new Map();
\\ 遍历数组进行读和存的判断
for(let i = 0; i < nums.length; i++) {
\\ 通过目标值-当前值拿到我们需要的值
let x = target - nums[i];
\\ 判断map中有无我们需要的值
if (map.has(x)) {
\\ 如果集合中有需要的值,则返回当前值的key
return [map.get(x), i];
}
\\ 如果集合中没有当前值,则把当前值存到map的key中
map.set(nums[i], i);
}
return [];
};