「这是我参与2022首次更文挑战的第32,活动详情查看:2022首次更文挑战」
1. 两数之和
给定一个整数数组 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) 的算法吗?
分析
两数之和这一题算是比较经典的一题了。根据题意我们只需要从数组 nums
中找出俩个数和为target
即可。这边需要注意的时候数组中同一个元素在答案里不能重复出现,这里的同一元素指的不是数值而是下标。比如 nums = [5,5,2] target=10
很显然我们应该返回[0,1]
。
了解完题目后我们再来说说解法,说到找俩个数我们应该会首先想到通过俩层循环就能就能找到两数之和。
说完基础解法我们再来说说进阶解法,我们可以通过Map对象对数组nums
内的元素进行记录当前下标与它需要数组的关系。这样我们就不需要遍历俩边nums
数组,第二个数直接从Map对象里取即可。当然不管是基础解法还是进阶解法我们都需要注意俩个数的下标是不能一样的。
分析完毕题目让我们直接来现实一波吧!!!
分步实现 暴力破解
遍历俩次nums
数组,判断nums[i]+nums[j]
是否等于target
并且我们需要判断i !== j
。如果为真我直接返回[i,j]
,否则继续下次循环。
for(let i = 0; i<nums.length; i++){
for(let j = 0; j<nums.length; j++){
if(nums[i]+nums[j] === target && i !== j){
return [i,j]
}
}
}
代码实现 暴力破解
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
for(let i = 0; i<nums.length; i++){
for(let j = 0; j<nums.length; j++){
if(nums[i]+nums[j] === target && i !== j){
return [i,j]
}
}
}
return []
};
分步实现 使用Map对象
定义一个map对象用于存放当前下标与需要数值的关系
let map = new Map()
判断当数值是否存在如果存在的话说明之前有与它相加和为target
的直接,直接返回当前下标与map对象存的下标。否则我们将当需要的目标数与当前下标存入map对象里即可。
for(let i = 0; i<nums.length; i++){
let num = nums[i]
if(map.has(num)){
return [map.get(num),i]
}else{
map.set(target-num,i)
}
}
代码实现 使用Map对象
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
let map = new Map()
for(let i = 0; i<nums.length; i++){
let num = nums[i]
if(map.has(num)){
return [map.get(num),i]
}else{
map.set(target-num,i)
}
}
return []
};