题目
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
解题
方法1:
刚开始,我选择了比较常用的方法,直接循环遍历数组,进行比较,代码如下:
let 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];
}
}
}
};
这是一种解决方式,但是,提交后,发现系统的评分并不高,内存占用和执行速度都只是排到了前50%~40%。
方法2:
我们来想一下,这个算法的复杂度是O(n^2),并不是很理想,并且,这个数组是杂乱无序的,如果是大量数据的情况下,恰好又是最后才会匹配成功,这种方式耗时就会非常久。
然后我们换种方式考虑,如果我们能够知道每个数差几能够整好到target值,并且我们整好能够知道差的这个数在数组中的下标,是不是就使得问题变得非常简单?
我们拿题目中的例子来进行举例:
[2,7,11,15]
第1步:我取第一个数2的时候,知道还差7才能到target值9,然后,我记录下来,后面数组中碰到数值是7的,数组下标是0的是满足条件的。
第2步:取到到第二个数7,则发现差2, 而2对应的下标是0,这对下标是满足条件的
后面我们考虑到,想要快速查到我取到的数是否有对应下标满足条件,就要记录信息,接下来就是空间换时间了。
具体实现方式就是下面这样,使用一个数组(或对象),如果temp[nums[i]]有值的话,则temp[num[i]]与i就是对应的一对满足条件的值:
let twoSum = function(nums, target) {
const len = nums.length,temp = [];
for(let i = 0; i < len; i++) {
let dif = target - nums[i];
if(temp[dif] !== undefined) {
return [temp[dif], i];
}
temp[nums[i]] = i;
}
}
最终我们获得的评分是:
这样的方式,我们尝试使用ES6的map来实现以下效果如何呢?
let twoSum = function(nums, target) {
const temp = new Map(),len = nums.length;
for (let i = 0;i<len;i++) {
let dif = target - nums[i];
if (temp.get(dif) !== undefined) {
return [temp.get(dif), i];
}
temp.set(nums[i],i);
}
}
效率方面也还是可以的
注:由于系统会使用不同的数据进行测试,所以不要过于纠结执行速度的精确性。
结语
以上是我对此题的解法,如果有小伙伴有更好的方式,或者非常有趣的思维方式,欢迎一起交流讨论。
希望此文能够解决大家工作和学习中的一些疑问,避免不必要的时间浪费,有不严谨的地方,也请大家批评指正,共同进步!
转载请注明出处,谢谢!