# 1. 两数之和

力扣题目链接 (opens new window)

给定一个整数数组 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 循环,对于每个元素,遍历它后面的所有元素,看有没有相加等于 target 的,时间复杂度 O(n²)。

能不能优化?

本题的核心需求是:遍历数组的时候,快速查找"之前有没有出现过某个元素"。

查询一个元素是否出现过——这就是哈希法的用武之地。

那么用什么哈希结构?

  • 数组:大小受限,如果元素值跨度大(比如 -10^9 到 10^9),空间浪费严重
  • set:只能存 key,但本题不仅要判断元素有没有出现过,还要知道它的下标,set 存不了下标
  • map:key 存元素值,value 存下标,正好满足需求

所以本题用 map。

接下来明确两个问题:

  • map 用来做什么——存放我们遍历过的元素,方便后续查询
  • map 中 key 和 value 分别存什么——key 存元素值(用来判断是否出现过),value 存下标(题目要返回的)

还需要注意一点:key 不能重复,且不需要有序,所以选择 unordered_map,查询效率 O(1)。

# 模拟过程

以 nums = [2, 7, 11, 15],target = 9 为例。

i = 0,nums[0] = 2:

查找 target - 2 = 7,map 为空,没找到。把 {2, 0} 存入 map。

i = 1,nums[1] = 7:

查找 target - 7 = 2,在 map 中找到了!key=2 对应 value=0,说明 nums[0] + nums[1] = 2 + 7 = 9。返回 [0, 1]。

# 解题代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> map; // key: 元素值, value: 下标
        for (int i = 0; i < nums.size(); i++) {
            auto iter = map.find(target - nums[i]); // 查找之前是否出现过配对元素
            if (iter != map.end()) {
                return {iter->second, i};
            }
            map.insert(pair<int, int>(nums[i], i)); // 没找到,把当前元素存入map
        }
        return {};
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14

时间复杂度:O(n)

空间复杂度:O(n)

# 其他语言

# Python3

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        records = dict()
        for index, value in enumerate(nums):
            if target - value in records:  # 查找之前是否出现过配对元素
                return [records[target - value], index]
            records[value] = index  # 没找到,把当前元素存入字典
        return []
1
2
3
4
5
6
7
8

# Java

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int temp = target - nums[i]; // 查找之前是否出现过配对元素
            if (map.containsKey(temp)) {
                return new int[]{map.get(temp), i};
            }
            map.put(nums[i], i); // 没找到,把当前元素存入map
        }
        return new int[0];
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# Go

func twoSum(nums []int, target int) []int {
    m := make(map[int]int)
    for i, num := range nums {
        complement := target - num
        if index, found := m[complement]; found { // 查找之前是否出现过配对元素
            return []int{index, i}
        }
        m[num] = i // 没找到,把当前元素存入map
    }
    return nil
}
1
2
3
4
5
6
7
8
9
10
11

# JS

var twoSum = function(nums, target) {
    let hash = {};
    for (let i = 0; i < nums.length; i++) {
        if (hash[target - nums[i]] !== undefined) { // 查找之前是否出现过配对元素
            return [hash[target - nums[i]], i];
        }
        hash[nums[i]] = i; // 没找到,把当前元素存入对象
    }
    return [];
};
1
2
3
4
5
6
7
8
9
10

# 与代码随想录联系

我在代码随想录哈希表章节里,详细讲解过什么时候用数组做哈希,什么时候用 set,什么时候用 map。

如果想系统学习哈希表,可以看一下代码随想录哈希表章节 (opens new window),从理论基础到实战题目都有覆盖。

和本题相关的题目:

上次更新:: 4/22/2026, 9:10:06 AM

评论

验证登录状态...