Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
leetcode第一题:两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
如nums=[1,2,3,5,0];target=8;那么输出结果应该是[2,3]。因为nums[2]+nums[3] = 3+5 =8
二、思路分析:
-
最直接的,我们可以直接两次循环,看两次循环中哪两个数相加可以等于target。当然两次循环的话,复杂度就是0(n²)。另外需要注意题目中一个元素不能同时出现,所有两层循环时,不能取同一个index的元素
-
用空间换时间:使用一个对象来映射数组中值。obj={},对数组nums进行一次遍历。每次循环在obj中找当前元素n需要的对应的元素target-n;当target-n不在对象中时,记录当前n和index;在下一次循环中继续判断有没有需要的对应值。相当于这样的:
- 循环数组,index=0,n=1时,需要target-1=7,在obj中查找有没有obj[7],发现没有,记录当前值和index,赋值obj[1]=0
- index=1,n=2时,检查obj中有没有
obj[target-n]即obj[6]发现没有则赋值记录当前index:obj[2]=1 - index=2,n=3时,index为2的位置需要5,判断有无obj[5],没有,记录赋值obj[3]=2
- index=3,n=5时,index为3时位置需要3,判断有obj[3],发现有,说明之前出现过3,当前值为5,满足要求,
return [obj[3], index]即[2,3]
三、AC 代码:
/**
* @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(i!==j&&nums[i]+nums[j]===target){
return [i,j]
}
}
}
// 解法二:定义obj,记录值和index,在循环时找target-n
let obj={}
for(let i=0;i<nums.length;i++){
let n = nums[i]
if(target-n in obj){ // 若值为0也是true;undefined才为false
// 表示找到了对应的两个值,当前值的index为i,对应值的index:obj[target-n]
return [obj[target-n], i]
}else{
// 没有找到对应值,则记录当前值和index
obj[n] = i
}
}
// 与解法二类似,我们可以记录当前值和index,同样可以记录需要的值target-n和当前index。表示第index的位置需要值target-n。在循环中查询当前值是不是某个需要的值(在obj中存在)
let obj={}
for(let i=0;i<nums.length;i++){
let n = nums[i]
if(n in obj){ // 若值为0也是true;undefined才为false
// 表示找到了对应的两个值,当前值的index为i,对应值的index:obj[n]
return [obj[n], i]
}else{
// 没有找到对应值,则记录当前值的index和需要的值
obj[target-n] = i
}
}
}
四、总结:
在算法思想中,使用空间换时间的思想很常见,上面这个小示例就是。其他情况下我们可以善加利用这种思想。