JS两数之和

859 阅读4分钟

👓题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 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]

示例 3:

输入: nums = [3,3], target = 6
输出: [0,1]

提示:

  • 2 <= nums.length <= 10(4)
  • -10(9) <= nums[i] <= 10(9)
  • -10(9) <= target <= 10(9)
  • 只会存在一个有效答案

🕶思路

第一个思路,使用了暴力枚举的思路,即通过两层for循环遍历数组中的所有元素对,并检查它们的和是否等于目标值。

另一个核心思路是利用哈希表来存储遍历过的元素和索引,以便在后续遍历中快速查找是否存在与当前元素相加等于目标值的另一个元素。

🥼方法一

虽然这种方法比较简单和直观,但是时间复杂度是O(n^2),时间效率不如使用哈希表的解法。

/**
 * 计算数组中两个数的和为目标值的索引对
 *
 * @param nums 整数数组
 * @param target 目标值
 * @returns 包含两个索引的数组,表示和为 target 的两个数的索引;如果找不到,则返回空数组
 */
let twoSum = function (nums, target) {
  for (let i = 0; i < nums.length; i++) {
    for (let j = 0; j < nums.length; j++) {
      if (nums[i] + nums[j] === target && i !== j) {
        return [i, j];
      }
    }
  }
  return [];
};

🧤方法二

使用哈希法的解法时间复杂度是O(n),因为我们只需要遍历一次数组。空间复杂度也是O(n),因为在最坏的情况下,我们可能需要将数组中的所有元素都存储到哈希表中。不过,由于这种解法在实际应用中通常能够快速地解决问题,因此它被广泛采用。

/**
 * 计算数组中两个数的和为目标值的索引对
 *
 * @param nums 整数数组
 * @param target 目标值
 * @returns 包含两个索引的数组,表示和为 target 的两个数的索引;如果找不到,则返回空数组
 */
let twoSum = function (nums, target) {
  let hash = {};
  // 遍历当前元素,并在map中寻找是否有匹配的key
  for (let i = 0; i < nums.length; i++) {
    if (hash[target - nums[i]] !== undefined) {
      return [hash[target - nums[i]], i];
    }
    // 如果没有找到匹配对,就把访问过的元素和下标加入到map中
    hash[nums[i]] = i;
  }
  return [];
};

🩲方法三

选择Map数据结构来存储数组元素及其索引,以便进行快速查找。

可以使用以下方法来操作Map对象中的元素。

  • has(key):检查Map对象中是否存在指定的键。
  • set(key, value):向Map对象中添加一个新的键值对。
  • get(key):根据键获取对应的值。
  • delete(key):从Map对象中删除指定的键值对。
/**
 * 计算数组中两个数的和为目标值的索引对
 *
 * @param nums 整数数组
 * @param target 目标值
 * @returns 包含两个索引的数组,表示和为 target 的两个数的索引;如果找不到,则返回空数组
 */
function twoSum(nums, target) {
  let map = new Map();
  for (let i = 0; i < nums.length; i++) {
    let num = nums[i];
    if (map.has(num)) {
      return [map.get(num), i];
    } else {
      map.set(target - num, i);
    }
  }
  return [];
}

🧥总结

本题其实有四个重点,把这四点想清楚了,本题才算是彻底理解了。

  • 为什么会想到用哈希表
  • 哈希表为什么用map
  • 本题map是用来存什么的
  • map中的key和value用来存什么的
  1. 为什么会想到用哈希表

当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。

  1. 哈希表为什么用map

在JavaScript中,Map 是一种内建的哈希表实现,它允许我们使用任何类型的键(key),不仅仅是字符串。在这个问题中,我们使用数字作为键,这是 Map 非常适合的场景。此外,Map 提供了简洁直观的 API 来进行键值的增删改查(set,get,has)操作。

  1. 本题map是用来存什么的

存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。

  1. map中的key和value用来存什么的

key来存元素,value来存下标。

📖参考笔记:代码随想录