LeetCode刷题笔记-1.两数之和(two-sum)
问题描述
给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。你可以按任意顺序返回答案。
说明:
2 <= nums.length <= 103-109 <= nums[i] <= 109-109 <= target <= 109- 只会存在一个有效答案
示例 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]
题解
1.暴力解法
算法解析
固定一个数,然后寻找满足条件的另一个数.算法主要通过两层循环实现,第一层循环每次固定一个数nums[i],直至遍历完数组.第二层循环从第一层循环固定的那个数的下一个数开始,逐个寻找之后的数nums[j].当发现满足条件nums[i] + nums[j] == target时返回结果.
复杂度分析
- 时间复杂度: \(O(N^2)\), 两层循环所以时间复杂度为\(O(N^2)\)
- 空间复杂度: \(O(1)\), 只需要固定的额外空间
代码实现
- Python版
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
n = len(nums)
for i in range(n):
for j in range(i+1, n):
if nums[i] + nums[j] == target:
return [i, j]
return []
2.哈希表解法
算法解析
由暴力解法可知,两层循环时间复杂度较高.设第一次固定的值为val,如果第二层循环可以通过哈希表直接查询数组中是否存在target - val便可将第二层循环时间复杂度降低到\(O(1)\).该哈希表应该以数组中的值为键,以对应的下标为值构建.这样通过查询是否存在键为target - val的方式便可快速的找到对应值和下标.对于该哈希表的构建方式有两种:
- 两次遍历,第一次遍历数组先构建哈希表,第二次遍历数组则固定值
val查询目标值target - val. - 一次遍历,在遍历数组的同时构建哈希表:
- 先查询表中是否存在与
val对应target - val值,有则直接返回结果. - 若查询失败,则将当前值
val为键,当前下标为值存入哈希表中,以待后面的对应值的查询. - 对于遍历第一个元素,由于哈希表为空,自然会将该值及其下标存入哈希表,等待以后查询.
- 对于重复的两个元素(重复的元素最多为2个)第一个会正常存入哈希表,第二个若为解则会直接返回,不会存入哈希表;若不是解,就算有哈希碰撞也不影响解.
- 先查询表中是否存在与
参考文章及资料
LeetCode官方题解 方法二:哈希表
LeetCode精选题解
复杂度分析
- 时间复杂度: \(O(N)\), 一层循环则时间复杂度为\(O(N)\)
- 空间复杂度: \(O(N)\), 构建该哈希表的空间复杂度一般为\(O(N)\)
代码实现
- Python版(两次遍历)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash_table = {k: v for v, k in enumerate(nums)}
for i, value in enumerate(nums):
search_key = target - value
# 当存在相同值为解时,由于哈希表存储的是第二个值的下标
# 而遍历时肯定为第一个值,所以一前一后不会产生冲突
# 当两个值相同时还需要跳过找到同一个元素的情况
if search_key in hash_table and i != hash_table[search_key]:
return [i, hash_table[search_key]]
return []
- Java版(一次遍历)
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> hashTable = new HashMap<>();
for (int i = 0; i < nums.length; ++i) {
int search_key = target - nums[i];
// 先查询是否存在与nums[i]对应的值,存在则返回结果
if (hashTable.containsKey(search_key)) {
return new int[]{hashTable.get(search_key), i};
} else { // 不存在时则存入哈希表,以待之后查询
hashTable.put(nums[i], i);
}
}
return new int[2];
}
}
解题误区及心得总结
心得总结
- 哈希表在保存状态且需要大量查询的时用处很大,也是空间换时间的典型.
- 本题在遍历数组同时构建哈希表既优化了运行速度又节省了内存,值得学习.

浙公网安备 33010602011771号