方案一,暴力双循环
读完题目,马上能想到的方案就是双循环,挨个排查,写出来也很快:
var twoSum = function(nums, target) {
const len = nums.length;
for (let i = 0; i < len; i+=1) {
const left = nums[i];
for (let j = i+1; j < len; j+=1) {
const right = nums[j]
if (left + right === target) {
return [i, j]
}
}
}
};
上面方案,最大的问题就是时间复制度为 O(n^2),所以我们可以想办法在此基础上优化。
方案二,Map
方案一的思路是,从头到尾挨个去计算数组中任意两个元素的和,然后与给定结果值进行比较,从而找到目标索引,这就导致必须得进行 O(n^2) 复杂度的双循环,效率低下。为了干掉双循环,我们不得不转换思考方式,如何才能在一次迭代中就实现题目要求呢。
题目本质是找到符合要求的两个数组元素的索引,不是非要双循环迭代两两配对求和后再比较。既然已经知道目标值,那么我们完全可以在一次迭代中,就计算出每个元素对于要达到这个和值所需要的另一个加数,然后在这一次迭代剩余的过程中进行比较确认。比如,[2, 7, 11, 15]
目标9
,对于 7
,只要找到数组元素 2
的索引值就行了,那么当我们一开始迭代到 2
时,就可以讲(7, 0)
这一组信息存储起来,当遍历到7
时即可直接使用。
这里,我们会发现,对于每个迭代的元素,我们需要存储两个东西:一个东西是需要的数组元素,一个是当前元素索引。对于选择存储类型而言,这两个东西是有关系的,应该两个一组一起存储,而且这种类型还必须具有很高的读写效率;基于此,我们选择使用 Map
。
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
var twoSum = function(nums, target) {
const len = nums.length;
const map = new Map();
for (let i = 0; i < len; i+=1) {
const currElem = nums[i];
const needNum = target - currElem;
if (map.has(needNum)) {
return [map.get(needNum), i]
}
map.set(currElem, i)
}
};
标签:const,双循环,迭代,nums,JavaScript,len,Leetcode,两数,target
From: https://www.cnblogs.com/astrofeyx/p/leetcode-problem-1-two-sum.html