LeetCode第一题 - 两数之和 (JS实现)

168 阅读2分钟

两数之和 题目链接

image.png

分析

输入: 整数数组nums, 整数目标值target
输出: 数组下标result
限制条件:
  1. 两个整数的和为目标值(即result的长度为2)
  2. 数组中同一个元素在答案里不能重复出现(即result的两个元素不同)
  3. 假设每种输入只会对应一个答案,可以按任意顺序返回答案(即result两个元素任意顺序均可,都视为一个答案)

方法一:暴力法(时间复杂度为o(n2)o(n^2))

暴力解决方案就是使用双层for循环,只需要注意边界条件,尽量减少不必要的循环。

Javascript 代码实现
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let result = [];
    for (let i=0; i< nums.length - 1; i++) { //注意边界条件
        for (let j=i+1; j<= nums.length - 1; j++) { // 注意边界条件
            if (nums[j] + nums[i] === target) {
                result = [i, j]
                return result
            }
        }
    }
    return result;
};

方法二:哈希表

当我们需要查询一个元素是否出现过,或者一个元素是否在集合里,就要第一时间想到哈希表。参考代码随想录

这道题我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,所以使用map存放正合适。 最终要返回下标,所以我们将下标作为value, 元素作为key。

Javascript 代码实现
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let result = [];
    // map中的存储结构为 { key:数据元素, value:数组元素对应的下标 }
    let map = new Map();
    for (let i=0; i<= nums.length - 1; i++) {
        if (map[target - nums[i]] !== undefined) { // 说明我们访问过的元素中有整数target-nums[i]
            result = [i, map[target-nums[i]]];
            return result;
        } 
        // map存放我们访问过的元素
        map[nums[i]] = i;   
    }
    return result;
};

一些思考

第一次刷这道题的时候,一直想不通的是以数组中的元素作为key值,很有可能重复呀,而map的key值不能重复,为何代码可以这么写?其实是因为题目中假设每种输入只会对应一个答案。

  • 如果有3个或者以上的重复元素,代表这个重复元素不可能是解(如果这个重复元素是我们要找的整数,那么答案就不唯一了)。

  • 如果有2个重复元素,要么不是解,写入map的时候因为key值重复被覆盖也无所谓;要么这两个重复元素的和就是target, 这时候已经return result了,第二个重复元素不会写入map, 所以这种情况在编码时已经考虑到了。