zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

Leetcode题1两数之和 JavaScript语言

2023-04-18 15:27:46 时间

1. 两数之和

方案一,暴力双循环

读完题目,马上能想到的方案就是双循环,挨个排查,写出来也很快:

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) 复杂度的双循环,效率低下。为了干掉双循环,我们不得不转换思考方式,如何才能在一次迭代中就实现题目要求呢。

题目本质是找到符合要求的两个数组元素的索引,不是非要双循环迭代以此两两配对求和后再比较。既然已经知道目标值,可以采取空间换时间的策略,用一个结构存储遍历过的每个元素和索引,然后我们完全可以仅仅只在一次迭代中,就实现题目要求。具体思路如下:

  1. 对于当前遍历元素,计算其相对于目标值所需的另一个加数
  2. 查找存储器是否有这样的加数,如果有,取得此加数的索引,算法结束
  3. 如果存储结构中找不到这样的加数,则将当前元素及其索引存入存储器,供后续遍历到的元素使用

比如,[2, 7, 11, 15]目标9,对于 2,其需要加数7,但是现在存储器为空,所以我们将元素2和其索引0存入存储器。然后当遍历来到元素7时,其需要加数2,查找存储结构发现有2,取得2的索引后与7的索引一同返回,问题即得解。

这里可以发现,对于当前遍历的元素,我们需要存储两个东西:一个东西是数组元素,一个是元素索引;且这两个东西是有关系的,应该两个一组一起存储。另外,我们的存储器必须具有 O(1) 读/写速度,基于以上考虑,我们选择使用 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)
    }

    return []
};

image