题目链接
题目描述
给定一个整数数组 nums
和一个目标值 target
,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
这是一个 核心代码模式 (Core Code Mode) 的题目,你只需要实现 twoSum
函数,无需处理任何输入输出。
示例: 输入:
nums = [0,7,2,1], target = 9
输出:
[1,2]
解释:
因为 nums[1] + nums[2]
等于 9, 所以返回 [1,2]
。
解题思路
这是一道非常经典的算法题。
暴力解法: 最直观的方法是使用两层循环。第一层循环枚举第一个数 nums[i]
,第二层循环从 i+1
开始枚举第二个数 nums[j]
,然后判断它们的和是否等于 target
。如果等于,就返回 [i, j]
。
- 时间复杂度:
- 空间复杂度:
这种方法在数据量较大时会超时。
哈希表法: 我们可以用空间换时间,将时间复杂度优化到 。
核心思想是:在遍历数组时,对于每个元素
x
,我们不再向后寻找 target - x
,而是反过来思考:之前是否已经遇到过 target - x
?
我们可以使用一个哈希表(在C++中是 unordered_map
,Java中是 HashMap
,Python中是 dict
)来存储已经遍历过的数字及其对应的下标。
算法步骤:
- 创建一个空的哈希表
map
。 - 遍历数组
nums
,对于每个元素nums[i]
: a. 计算需要的另一个数complement = target - nums[i]
。 b. 在哈希表map
中查找是否存在键complement
。- 如果存在,说明我们找到了解。
complement
对应的下标就是map[complement]
,当前数的下标是i
。直接返回{map[complement], i}
。 - 如果不存在,说明到目前为止还没遇到能和
nums[i]
配对的数。我们将当前的数和它的下标存入哈希表,即map[nums[i]] = i
,以便后续的元素进行查找。
- 如果存在,说明我们找到了解。
题目保证有唯一解,所以我们总能找到答案。这种方法只遍历数组一次,效率很高。
代码
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param nums int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> map;
for (int i = 0; i < nums.size(); ++i) {
int complement = target - nums[i];
if (map.count(complement)) {
return {map[complement] + 1, i + 1};
}
map[nums[i]] = i;
}
return {}; // 题目保证有解,这里是为了编译通过
}
};
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param nums int整型一维数组
* @param target int整型
* @return int整型一维数组
*/
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[]{map.get(complement) + 1, i + 1};
}
map.put(nums[i], i);
}
// 题目保证有解,这里是为了编译通过
throw new IllegalArgumentException("No two sum solution");
}
}
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param nums int整型一维数组
# @param target int整型
# @return int整型一维数组
#
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash_map = {}
for i, num in enumerate(nums):
complement = target - num
if complement in hash_map:
return [hash_map[complement] + 1, i + 1]
hash_map[num] = i
return [] # 题目保证有解,代码逻辑上不会执行到这里
算法及复杂度
- 算法: 哈希表
- 时间复杂度:
。我们只需要遍历一次数组。对于每个元素,哈希表的插入和查找操作的平均时间复杂度都是
。
- 空间复杂度:
。在最坏的情况下,我们需要将数组中的所有
个元素都存入哈希表中。