【Leetcode hot 100】1.两数之和
题目链接
- 两数之和
问题描述
给定一个整数数组 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]
问题解决
方法一:哈希表优化(推荐,时间复杂度 O(n))
核心思路
利用 哈希表(HashMap
) 记录已遍历的数字及其索引,将“查找互补数”的操作从 O(n) 优化到 O(1):
- 遍历数组时,对当前数字
nums[i]
,计算其与目标值的 互补数complement = target - nums[i]
。 - 若互补数已存在于哈希表中,说明找到符合条件的两个数,直接返回两者的索引。
- 若不存在,将当前数字和其索引存入哈希表,供后续遍历使用。
代码实现
import java.util.HashMap;
import java.util.Map;class Solution {public int[] twoSum(int[] nums, int target) {// 哈希表:键为数组元素值,值为对应索引Map<Integer, Integer> numMap = new HashMap<>();for (int i = 0; i < nums.length; i++) {int complement = target - nums[i]; // 计算互补数// 若互补数已存在,直接返回结果if (numMap.containsKey(complement)) {return new int[]{numMap.get(complement), i};}// 否则,将当前数字和索引存入哈希表numMap.put(nums[i], i);}// 题目保证有解,此处仅为语法兼容(实际不会执行)return new int[]{};}
}
代码解释
- 哈希表
numMap
:存储已遍历的 数字 → 索引 映射,支持快速查找(containsKey
和get
操作均为O(1)
)。 - 遍历逻辑:
- 对每个数字
nums[i]
,先计算互补数complement
,优先检查互补数是否已存在(避免重复使用同一元素,例如nums = [3,3]
,target=6
时,第一次存3→0
,第二次查complement=3
存在,返回[0,1]
)。 - 若互补数不存在,再将当前数字存入哈希表,保证后续遍历能找到它。
- 对每个数字
方法二:暴力枚举(直观但低效,时间复杂度 O(n²))
核心思路
通过 两层嵌套循环 枚举所有可能的数对 (nums[i], nums[j])
(i < j
,避免重复),检查它们的和是否等于 target
。
代码实现
class Solution {public int[] twoSum(int[] nums, int target) {// 外层循环:固定第一个数的索引 ifor (int i = 0; i < nums.length; i++) {// 内层循环:遍历 i 之后的数,避免重复计算for (int j = i + 1; j < nums.length; j++) {if (nums[i] + nums[j] == target) {return new int[]{i, j};}}}// 题目保证有解,此处仅为语法兼容return new int[]{};}
}
优缺点分析
- 优点:逻辑直观,无需额外空间(空间复杂度
O(1)
)。 - 缺点:时间复杂度 O(n²),当数组很大时(如
n=10^4
),性能会急剧下降(10^8
次运算)。
复杂度对比
方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
哈希表优化 | O(n) | O(n) | 大数据量 |
暴力枚举 | O(n²) | O(1) | 小数据量 |
实际工程中,哈希表优化法 是更优的选择,也是 LeetCode 该题的推荐解法。