导航菜单

两数之和

🟢 简单

题目描述

给定一个整数数组 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
  • 只存在一个有效答案

解法一

参考答案 (2 个标签)
暴力枚举 O(n²)

思路

使用两层循环,外层循环遍历每个元素,内层循环查找是否存在另一个元素使得两数之和等于目标值。

代码实现

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
function twoSum(nums, target) {
    const n = nums.length;
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            if (nums[i] + nums[j] === target) {
                return [i, j];
            }
        }
    }
    return [];
}

复杂度分析

  • 时间复杂度:O(n²),其中 n 是数组长度。最坏情况下需要遍历所有数对。
  • 空间复杂度:O(1),只使用常数级别的额外空间。

解法二

参考答案 (2 个标签)
哈希表 O(n)

思路

利用哈希表存储已经遍历过的元素及其下标。对于每个元素 nums[i],检查 target - nums[i] 是否在哈希表中,如果存在则找到了答案。

代码实现

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
function twoSum(nums, target) {
    const map = new Map();
    
    for (let i = 0; i < nums.length; i++) {
        const complement = target - nums[i];
        
        if (map.has(complement)) {
            return [map.get(complement), i];
        }
        
        map.set(nums[i], i);
    }
    
    return [];
}

复杂度分析

  • 时间复杂度:O(n),只需要遍历一次数组。
  • 空间复杂度:O(n),哈希表最多存储 n 个元素。

为什么先检查再插入?

注意代码中先检查 complement 是否存在,再插入当前元素。这样可以避免同一个元素被使用两次的情况。例如 nums = [3, 3], target = 6,如果先插入再检查,第一个 3 插入后,检查时发现 complement = 3 存在,但那是自己,会得到错误答案。

搜索