在LeetCode做简单数组题的第2天
学习错题复盘日志,面向初学者,记录自己踩坑、思考、顿悟的全过程,不是单纯题解。
前言
本人专业属于计算机大类,但基本不能主动回忆专业知识,目前在LeetCode做简单数组题。今天做到第1题两数之和,用到的哈希表相关知识,也是数据结构课学完很久几乎忘干净。
本文记录我的思考过程、bug、和对哈希表的理解,当作错题存档,方便以后回来复习。
题目:LeetCode 1.两数之和
描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。可以按任意顺序返回答案。
测试示例1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:nums[0] + nums[1] = 9
测试示例2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
测试示例3:
输入:nums = [3,3], target = 6
输出:[0,1]
一、蘑菇的简单思路
循环遍历数组里每一个元素nums[i],用 target - nums[i] 得到需要配对的另一半divide。
判断divide是否存在数组中,如果存在,还要保证这个另一半不能是当前这个元素本身;找到两个下标,返回结果。
一开始写代码就出现语法错误:
# 错误代码
for i in range(nums): # ❌错误:range里面必须传数字,应该是range(len(nums))
基础语法知识:range() 是 Python 中的一个内置函数,用于生成一个整数序列,常用于循环操作。它支持三个参数:start(起始值)、stop(结束值,不包含)和 step(步长)。
此外,找列表的元素下标虽然可用nums.index()可以实现,但是index()只会返回第一个匹配元素下标,且找不到会报错,只能用来理解思路,不适合正式提交。
二、蘑菇的解法:双层暴力循环
代码
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): # j从i后面开始,避免重复使用同一个元素
if nums[i] + nums[j] == target:
return [i, j]
思路解释
固定外层下标i,内层j从i的下一个位置开始,两两组合尝试相加,一旦相加等于target,直接返回两个下标。
复杂度
- 时间复杂度:O(n^2),两层循环
- 空间复杂度:O(1),只使用了i,j两个临时变量,没有额外开辟大空间
缺点:数组很长的时候效率差。
三、最优解法:哈希表(字典)
完整代码
class Solution:
def twoSum(self, nums: list[int], target: int) -> list[int]:
hashmap = {} # 初始化空字典!key存数组的值,value存对应的下标
for i, num in enumerate(nums):
divide = target - num
# 第一步:先查表,看我们需要的另一半是否已经记录在字典里
if divide in hashmap:
return [hashmap[divide], i]
# 第二步:查不到,才把当前数字和下标存入字典
hashmap[num] = i
enumerate() 是 Python 的内置函数,用于在遍历可迭代对象时同时获取元素的索引和值。它返回一个可迭代对象,常用于需要索引和值的场景。
✅我当时的疑惑解答
hashmap = {},一开始就是空字典,不是自带数据。字典是遍历过程中一点点写入的,像一个记事本。- 顺序绝对不能颠倒:先查找,后存入!
如果先存入当前数字再查找,会找到元素自己,返回同一个下标,违反题目“不能使用两次相同元素”的要求。 - 字典查找
divide in hashmap平均是O(1),数组查找divide in nums是O(n)。通俗理解:字典就像通讯录,输入名字直接找到人;数组查找需要从头挨个翻。
手动模拟样例
nums=[3,3], target=6
- 初始 hashmap = {}
- i=0,num=3
divide = 6 - 3 = 3
判断:3不在空字典{} → 存入 hashmap[3]=0,hashmap={3:0}. - i=1,num=3
divide = 6 - 3 = 3
判断:3 在hashmap里面,hashmap[3]=0
返回 [0,1] ✅
再模拟 nums=[3,2,4], target=6
- 初始 hashmap={}
- i=0 num=3,divide=3,不在字典 → 存入
- i=1 num=2,divide=4,不在字典 → 存入
- i=2 num=4,divide=2,2存在,hashmap[2]=1 → 返回[1,2] ✅
复杂度
- 时间复杂度:O(n),只遍历数组一遍,哈希查找近似常数时间。
- 空间复杂度:O(n),需要开辟字典存储遍历过的数据。
核心思想:用空间换取更快的速度。
四、两种方法对比总结
| 方法 | 时间复杂度 | 空间复杂度 | 特点 |
|---|---|---|---|
| 双层暴力循环 | O(n^2) | O(1) | 逻辑简单,大数据慢 |
| 哈希字典 | O(n) | O(n) | 速度快,需要额外内存 |
五、总结
- 基础语法坑:
range()里面只能放整数,遍历下标要用range(len(nums))。 - 哈希表核心:创建字典,边遍历边记录,先查,后存,字典初始是空。
- 时间复杂度:一层循环O(n),双层嵌套O(n^2)。
- 刷题方式:继续采用这种错题复盘模式,把思考过程、bug写下来,方便可以回顾。
学习计划回顾:现阶段巩固 Python 基础,只做LeetCode 简单题,重点训练独立写代码,不会深入复杂的部分。
六、本题自测
nums = [5, 1, 9], target =10,手动推演哈希解法,写出返回结果。
浙公网安备 33010602011771号