这次,我决定回顾一下我在leetcode上做的第一题,看了下提交记录,没想到已经是两年前了。
原题链接:1. 两数之和
一、先看题
给定一个整数数组 nums 和一个整数目标值 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]
提示:
- 只会存在一个有效答案
二、整理思路
依稀记得第一次做的时候用的是暴力法遍历了两次,然后超时了。这次拿到手之后,想了一下,直观的解法还是遍历,但是不用两次,而是用indexOf来替代遍历,同时通过条件进行剪枝,一次通过了测试用例。
第一步:
确认输入输出:
输入:一个数组;输出:一个数组。
第二步
怎么处理输入才能得到输出?
既然要找配对的元素,那么至少需要一次遍历,优化的难点就在于,怎么减少遍历的数量。
初步的写法是通过剪枝来优化:
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
let res=[]
for(let i=0;i<nums.length;i++){
//无论是大于还是小于都可以,只是为了减少一半的计算量
if(target-nums[i]<=nums[i]){
let idx=nums.indexOf(target-nums[i])
//由于用的是indexOf,有可能找到自己
//所以一定要加下标判断
if(i!=idx&&idx>=0){ res=[i,idx]}
}
}
return res
};
剪枝之后,计算的速度提升了不少,至少不会超时了。不过依稀觉得这依然不是最好的方法,于是参考了一下题解,看完恍然大悟,用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 rest = target-nums[i]
if(map.has(rest){
return [map.get(rest),i]
}else{
map.set(nums[i],i)
}
}
};
使用Map来进行下标的记录和查找,既不用担心找到本身,也减少了内存的消耗,更重要的是,代码思路一目了然。
三、总结
知识点:求和
解题法:剪枝法;哈希表
作为当初入坑leetcode的第一题,时隔两年再做有一些不一样的感受。时光易逝,把握现在把。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情