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]
python
# 先用暴力破解法
class Solution:
def twoSum(self, nums: list[int], target: int) -> list[int]:
# 索引和元素都要
# 从第一个元素开始逐个元素遍历
for i,item in enumerate(nums):
# 从第二个元素开始逐个取
# 让按住的第一个元素,和第二个元素对比,看是否相等
for j in range(i+1,len(nums)):
post=nums[j]
# 如果按住的那个和后面移动的那个 之和 等于 target说明找到了
if item+post==target:
return [i,j]
# 只是速度太慢了
哈希表自带快速搜索功能,使用这个
python
# 用哈希表
class Solution:
def twoSum(self, nums: list[int], target: int) -> list[int]:
# python里面哈希表就是字典
# 哈希表有一个强行的规定,key不能重复
cache={}
# 先将数据存入哈希表中
for i,item in enumerate(nums):
# item作为key, i作为value
cache[item] = i
# 现在,去找与它之和等于target的那个元素
# 遍历nums里面每一个元素
for i,item in enumerate(nums):
# 要找的东西是什么先给出来具体的值
other=target-item
# 如果这个要找的值在nums里面
# 且这个被找到的数字的 索引index不等于 item的index i
# 因为要把当前的元素排除出去。cache[other]==i 的元素都不会经过这里,把非当前元素保留
if other in cache and cache[other]!=i:
return[i,cache[other]]
对于后面这个例子输入:nums = 3,3, target = 6
输出:0,1,请问两个相同的元素3能放进同一个dict cache里面去吗?
**不能同时保留两个 3 的索引。**在 Python 字典中,键(key)必须是唯一的,后写入的相同键会直接覆盖前面的值。
具体分析 nums = [3, 3], target = 6 的情况
1. 建表阶段
当循环执行 cache[item] = i 时:
- 第一次循环:
i=0, item=3,字典变为{3: 0} - 第二次循环:
i=1, item=3,由于键3已存在,新值1会覆盖旧值0,字典最终变为{3: 1}
所以,第一个 3 的下标 0 在字典中已经丢失了。
2. 查找阶段
- 当
i=0, item=3时,计算other = 6 - 3 = 3。 - 检查
3 in cache→ 成立。 - 检查
cache[3] != i→ 即1 != 0→ 成立。 - 返回
[0, 1],结果正确。
为什么这段代码依然能通过?
虽然字典里只保留了最后一个 3 的索引,但恰好够用 。因为题目保证只有一个答案,且不能用同一个元素两次。当遍历到第一个 3(i=0)时,字典里存的是第二个 3(i=1),cache[other] != i 这个判断保证了不会把同一个位置的元素用两次。
但这段代码其实有隐患
如果输入是 nums = [3, 3, 3], target = 6:
- 建表后
cache = {3: 2}(只保留了最后一个索引) - 当
i=2, item=3时,other=3,cache[3]=2,此时cache[other] == i,条件不成立,会漏掉[2, 1]或[2, 0]这样的组合。
当然,题目说了"每种输入只会对应一个答案",所以这种情况不会出现。
更优的方式
python
class Solution:
def twoSum(self, nums: list[int], target: int) -> list[int]:
cache = {}
for i, item in enumerate(nums):
other = target - item
if other in cache:
return [cache[other], i]
cache[item] = i # 当前元素放入字典,供后面的元素查找
举个例子模拟运行
假设 nums = [2, 7, 11, 15], target = 9。
第 1 轮循环 (i=0, item=2)
other = 9 - 2 = 7- 检查
7 in cache?此时cache是空的{},所以 不在。 - 执行
cache[2] = 0。现在cache = {2: 0}。 - (你看,这一轮没找到,但把 2 存进去了,方便后面的人找它)
第 2 轮循环 (i=1, item=7)
other = 9 - 7 = 2- 检查
2 in cache?此时cache = {2: 0},在! - 既然在,说明之前已经遇到过
2了。 - 直接返回
[cache[2], 1],也就是[0, 1]。
什么
cache[other]能取出元素?
因为 other 是当前元素 需要的搭档。如果 other in cache 成立,说明这个搭档是之前的某次循环中已经被存进字典里的。
- 当
item=7时,它需要的搭档是2。 2是在上一轮 (i=0) 被存进cache的。- 所以
cache[2]能成功取出0。