题目
给定一个整数数组 nums 和目标值 target,找出两个下标,使得对应元素之和等于 target。
题目分析
这道题很适合作为算法题解入门题,因为它的优化路径非常直白:
- 先想到最直接的双重循环
- 再思考怎样避免重复查找
- 最后自然过渡到哈希表
核心问题其实只有一个:当我们遍历到当前数字时,能不能立刻知道它需要的“另一个数”是否已经出现过。
方法一:直觉解法
最直接的写法就是枚举所有二元组。
1func twoSumBruteForce(nums []int, target int) []int {
2 for i := 0; i < len(nums); i++ {
3 for j := i + 1; j < len(nums); j++ {
4 if nums[i]+nums[j] == target {
5 return []int{i, j}
6 }
7 }
8 }
9 return nil
10}
这个方法容易理解,但时间复杂度是 O(n^2)。
方法二:优化思路
如果我们在遍历到 nums[i] 时,已经知道前面每个数字出现过的位置,那么只要算出 target-nums[i],就能马上判断答案是否已经出现过。
这正好对应哈希表:
- key:数值
- value:下标
Go 实现
1func twoSum(nums []int, target int) []int {
2 indexByValue := make(map[int]int, len(nums))
3 for i, num := range nums {
4 need := target - num
5 if j, ok := indexByValue[need]; ok {
6 return []int{j, i}
7 }
8 indexByValue[num] = i
9 }
10 return nil
11}
复杂度分析
- 时间复杂度:
O(n) - 空间复杂度:
O(n)
易错点
- 一定要先查哈希表,再插入当前值,避免把同一个元素使用两次
- 如果题目要求返回的是下标,map 的 value 应该存位置,而不是计数
我的复盘
这题最大的价值,不是哈希表本身,而是让我再次确认了一件事:很多优化并不复杂,关键是把“重复做的事”显式找出来。
关联题
- 两数之和 II
- 三数之和
- 四数之和