新手leetcode快速刷题指南
新手leetcode快速刷题指南
- 前言:
- 我们的新手LeetCode刷题入门指南:
- python基础语法与数据结构
- leetcode刷题通用解题流程:
- 如何在本地编译测试 LeetCode 代码
- 4) 如何自己设计测试样例?
- Python高效刷题题单:
前言:
我们现在准备刷题了,时间紧、任务重,希望快速上手。只学对刷题最有用的 20% Python 知识,先能写题、跑通、过样例,再逐步变强。
首先我们刷题前要知道的
- 我们在 LeetCode 写的 Python算法题,绝大多数都是:
用 list/dict(数组/哈希表)+ 循环 + if,配合几个常用库(collections / heapq / bisect / functools)和固定模板(双指针/栈/队列/BFS/二分/回溯/DP)就能解决:
然后开始我们的新手LeetCode刷题入门指南。
我们的新手LeetCode刷题入门指南:
python基础语法与数据结构
- 数据类型:
int,float,str,list,dict,set,tuple - 控制结构:
if/else,for,while - 函数:定义
def, 参数与返回值 - 列表推导式(简洁写法)
- 常见内置函数:
len,sum,max,min,sorted,enumerate,zip - 字符串操作:
split,join,strip,replace - 常用库(入门阶段先知道即可):
collections,math
🧩 一、Python 基础语法概览
| 模块 | 要掌握的知识 | 关键语法 | 举例 | 对刷题的帮助 |
|---|---|---|---|---|
| 变量与类型 | 不需要声明类型,直接赋值即可 | a = 10、b = "hi" | x = 3.14、name = "Alice" | 编程更快,不用int/char定义 |
| 输入输出 | input()读入字符串;print()输出 | s = input();print(x) | print("答案:", ans) | 用来调试或输出结果 |
| 注释 | 单行用 #,多行用三引号 | # 这是注释 | '''多行注释''' | 写题解说明、调试 |
| 缩进 | 控制代码块,无大括号 {} | if x>0:\n print(x) | – | 必须保持统一(常为4空格) |
🧮 二、数据类型(核心:list、dict、str)
| 类型 | 定义方式 | 常用操作 | 示例 | 刷题用途 |
|---|---|---|---|---|
| int / float | a = 10;b = 3.14 | + - * / // % | 5 // 2 -> 2(整除) | 计数、取模、循环控制 |
| str(字符串) | 'abc' 或 "abc" | s[i]取字符;len(s)长度 | "abc"[1] -> 'b' | 处理文本、回文串 |
| list(列表) | [1, 2, 3] | append(x),pop(),len(),切片a[1:3] | nums = [1,2,3]; nums.append(4) | 最常用容器! |
| dict(字典/哈希表) | {"a":1, "b":2} | d["a"]取值;d.keys();d.get("x",0) | cnt = {"a":1};cnt["a"]+=1 | 高频题结构(Two Sum) |
| set(集合) | {1,2,3} | add(x),remove(x),in判断 | s = {1,2}; 3 in s -> False | 去重、判断是否出现 |
| tuple(元组) | (1,2,3) | 不可修改,用于返回多个值 | return (x, y) | 函数多返回值、排序key |
🔁 三、控制结构(逻辑与循环)
| 结构 | Python写法 | 示例 | 说明 |
|---|---|---|---|
| if / elif / else | if 条件: | if x>0:\n print("正")\nelif x==0:\n print("零")\nelse:\n print("负") | 注意冒号:和缩进 |
| for循环 | for 变量 in 序列: | for i in range(5): print(i) | range(n)表示0到n-1 |
| while循环 | while 条件: | while n>0:\n n-=1 | 同C语言逻辑 |
| break / continue | 同C语言 | if i==3: break | 控制循环流 |
| for…else(特殊) | 循环正常结束后执行else | 搜索时常用 | 不掌握也行,了解即可 |
🧰 四、函数(刷题常用模板)
| 内容 | 语法 | 示例 | 说明 |
|---|---|---|---|
| 定义函数 | def 函数名(参数): | def add(a,b): return a+b | 没有类型声明 |
| 返回值 | return | return x, y | 可返回多个值 |
| 默认参数 | def f(x=0): ... | f() = f(0) | 常用在递归中 |
| 匿名函数 | lambda x: x+1 | map(lambda x:x+1, arr) | 列表排序、函数式操作 |
🧩 四点五、函数参数怎么传?
Python 传参基本就是“传对象的引用”。
关键是:int/str/tuple不可变对象:函数里改它,外面不变。list/dict/set可变对象:函数里改内容,外面会变。
常见错误1:不要用可变对象当默认参数(可变对象默认参数正确写法)
❌ 错误做法:
deff(path=[]): path.append(1)return path - 默认参数
path=[]在函数定义时初始化一次,之后每次函数调用都使用这个初始生成的同一个列表。
✅ 正确做法:
deff(path=None):if path isNone: path =[] path.append(1)return path - 使用
None作为默认值,每次函数调用时都会创建一个新的空列表。 - 避免了默认参数值被共享的问题,每次调用都返回一个独立的列表。
常见错误2:回溯/DFS里要用path[:]等浅拷贝
因为 path 是 list(可变),你要“存档一份当时的快照”,就得拷贝:
ans =[] path =[]defdfs(i):if i ==3: ans.append(path[:])# 关键:拷贝一份return path.append(i) dfs(i+1) path.pop() dfs(0)print(ans)(这里可以看一下我们上一篇的帖子,了解一下常见的直接赋值,浅拷贝,深拷贝的错误和理解。)
🧮 五、return
| 目的 | 写法 | 例子 |
|---|---|---|
| 返回单个值 | return value | return "ok" |
| 返回多个值 | return a, b, c | return q, r |
| 返回列表 | return [ ... ] | return [i, j] |
| 返回字典 | return { ... } | return {"a":1,"b":2} |
| 不返回/占位 | return 或省略 | return(等价 None) |
补充说明pass
如果你的函数暂时不需要写什么内容,可以补充一个pass当占位符
pass 语句:用于语法上需要语句但什么也不做的场景(如函数、类、循环的占位),例如:
deftodo():pass# 暂时不写实现if condition:pass# 稍后处理🧩 六、列表推导式(Python简洁写法)
| 功能 | 语法 | 示例 | 说明 |
|---|---|---|---|
| 创建列表 | [表达式 for 变量 in 序列] | [i*i for i in range(5)] → [0,1,4,9,16] | 简洁、常用 |
| 带条件 | [x for x in nums if x>0] | [x for x in [1,-2,3] if x>0] → [1,3] | 常用于过滤 |
💡刷题常见用法:
nums =[int(x)for x ininput().split()](把输入的一行数字变成整型数组)
🔧 七、常用内置函数
| 函数 | 用法 | 示例 | 常见用途 |
|---|---|---|---|
len() | 求长度 | len(nums) | 数组、字符串长度 |
sum() | 求和 | sum(nums) | 快速统计 |
max() / min() | 最大/最小 | max(nums) | |
sorted() | 排序 | sorted(nums, reverse=True) | |
enumerate() | 获取下标和值 | for i, val in enumerate(nums): | 常用于遍历 |
zip() | 打包多个序列 | for a,b in zip(nums1,nums2): | 同步遍历两个数组 |
any() | 任一为真 | any(x<0 for x in nums) | 条件判断 |
all() | 全部为真 | all(x>=0 for x in nums) | 条件判断 |
🔤 八、字符串操作(常考!)
| 操作 | 用法 | 示例 | 说明 |
|---|---|---|---|
split() | 按空格拆分字符串 | "a b c".split() → ['a','b','c'] | 输入解析 |
join() | 合并列表为字符串 | ",".join(['a','b']) → "a,b" | 输出格式化 |
strip() | 去掉首尾空白 | " abc ".strip() → "abc" | |
replace() | 替换子串 | "aba".replace('a','x') → "xbx" | |
| 切片 | s[l:r] | "abcd"[1:3]="bc" | 子串 |
🧮 九、常用库(刷题只需了解)
| 库/工具 | 一句话核心功能(新手友好版) | 最简示例(可以直接抄) | 常用场景 |
|---|---|---|---|
math | 常用数学计算(平方根、向上取整、最大公约数等) | math.sqrt(x)math.ceil(x)math.gcd(a,b) | 数论、几何、计算题 |
collections.Counter | 统计列表元素出现次数 | cnt = Counter(nums) | 频次统计、词频分析 |
collections.defaultdict | 访问不存在的键时自动初始化默认值 | d = defaultdict(list)d[key].append(val) | 分组统计、邻接表 |
collections.deque | 双端队列:头尾都能快速增删 | q = deque([1,2])q.append(3); q.popleft() | BFS、滑动窗口 |
heapq | 最小堆:随时获取最小值 | heappush(h, x)min_val = heappop(h) | TopK、合并有序列表 |
bisect | 二分查找:在有序列表中找插入位置 | pos = bisect_left(arr, x) | 二分搜索边界 |
functools.lru_cache | 记忆化装饰器:缓存递归结果 | @lru_cache(maxsize=None) | 递归DP、记忆化搜索 |
leetcode刷题通用解题流程:
1. 最实用的 5 步:
- 读题 + 确认输入输出(是否有序?允许重复?范围?)
- 选方法(哈希/双指针/栈/队列/BFS/二分/回溯/DP…)
- 估复杂度(目标一般 O(n) 或 O(n log n))
- 写代码(先写最小可行版本跑通样例)
- 测边界(空、单元素、极端、重复、负数/特殊字符)
2. 🥉常用算法分类
目标:能分析时间复杂度、选择合适的数据结构解题。
目标:能看出题目属于哪一类,直接套模板。
- 哈希表
- 双指针 / 滑动窗口
- 栈
- 队列 / BFS
- 二分查找
- 递归 / 回溯
- 动态规划(DP)
- 堆(TopK/最小最大)
3. 🧠 刷题最常用的 8 个 Python 小技巧
1)复杂度(先会这三句就能选方法)
- 扫一遍数组:通常 O(n)
- 排序:通常 O(n log n)
- 双重循环:通常 O(n^2)(n 大会超时)
2)排序怎么写(LeetCode 高频)
a.sort()# 升序 a.sort(reverse=True)# 降序 a.sort(key=lambda x: x[1])# 按第2个元素排序(二维数组/区间)3)哈希表计数(不用写 if)
from collections import defaultdict cnt = defaultdict(int)for x in nums: cnt[x]+=14)队列 BFS(树/图最常用)
from collections import deque q = deque([start])while q: cur = q.popleft()5)TopK / “总拿最小的那个”(用堆)
import heapq h =[] heapq.heappush(h,3) heapq.heappush(h,1) x = heapq.heappop(h)# 1(最小的先出来)6)二分(找“左边界/插入位置”)
from bisect import bisect_left i = bisect_left([1,2,4,4,7],4)# i == 27)递归记忆化(避免重复计算,DP/搜索常用)
from functools import lru_cache @lru_cache(None)deff(i):if i <=1:return1return f(i-1)+ f(i-2)8)list 的拷贝(刷题很常用)
b = a[:]# 拷贝一份(避免一起变)# ans.append(path[:]) 也是同样道理题型模板区(直接抄)
1)哈希表模板(Two Sum 类)
classSolution:deftwoSum(self, nums, target): pos ={}for i, x inenumerate(nums): y = target - x if y in pos:return[pos[y], i] pos[x]= i return[]2)双指针模板(有序数组/左右夹逼)
classSolution:deftwoSumSorted(self, nums, target): l, r =0,len(nums)-1while l < r: s = nums[l]+ nums[r]if s == target:return[l, r]elif s < target: l +=1else: r -=1return[-1,-1]3)滑动窗口模板(最长/最短子数组)
classSolution:defminSubArrayLen(self, target, nums): n =len(nums) l =0 s =0 ans =float('inf')for r inrange(n): s += nums[r]while s >= target: ans =min(ans, r - l +1) s -= nums[l] l +=1return0if ans ==float('inf')else ans 4)栈模板(有效括号)
classSolution:defisValid(self, s:str)->bool: pair ={')':'(',']':'[','}':'{'} st =[]for ch in s:if ch in"([{": st.append(ch)else:ifnot st or st[-1]!= pair.get(ch,'#'):returnFalse st.pop()returnnot st 5)BFS 队列模板(最短路径/层序遍历)
from collections import deque classSolution:defbfs(self, start): q = deque([start]) visited =set([start])while q: cur = q.popleft()# 处理 curfor nxt in[]:# 这里替换成邻居列表if nxt notin visited: visited.add(nxt) q.append(nxt)6)二分模板(找左边界)
classSolution:deflowerBound(self, nums, target): l, r =0,len(nums)# 注意 r = len(nums)while l < r: mid =(l + r)//2if nums[mid]>= target: r = mid else: l = mid +1return l 7)回溯模板(子集/组合)
classSolution:defsubsets(self, nums): ans =[] path =[]defdfs(i):if i ==len(nums): ans.append(path[:])# 拷贝快照return# 不选 dfs(i +1)# 选 path.append(nums[i]) dfs(i +1) path.pop() dfs(0)return ans 8)DP 模板(爬楼梯)
classSolution:defclimbStairs(self, n:int)->int:if n <=2:return n a, b =1,2for _ inrange(3, n +1): a, b = b, a + b return b 如何在本地编译测试 LeetCode 代码
1)站内模板(LeetCode)
classSolution:defyourMethod(self,...):# 1) 参数检查(可选)# 2) 初始化# 3) 主循环 / 递归# 4) 返回结果pass2)本地模板(使用断言)
classSolution:defyourMethod(self, param1, param2):# 你的方法实现passdeftest_your_method(): s = Solution()assert s.yourMethod(param1, param2)=="expected_value"if __name__ =="__main__": test_your_method()print("All tests passed.")3)本地示例:Two Sum(哈希表)
- LeetCode 页面有「自定义测试用例」输入框,直接贴 JSON 风格输入即可。
- 例如 Two Sum:
- 本地使用断言测试时,把这些样例输入我们创建的方法入口中
输入:
[2,7,11,15] 9 …… classSolution:deftwoSum(self, nums, target): pos ={}for i, x inenumerate(nums): y = target - x if y in pos:return[pos[y], i] pos[x]= i return[]deftest_two_sum(): s = Solution()assert s.twoSum([2,7,11,15],9)==[0,1]assert s.twoSum([3,3],6)==[0,1]assert s.twoSum([-1,-2,-3,-4,-5],-8)==[2,4]if __name__ =="__main__": test_two_sum()print("All tests passed.")4) 如何自己设计测试样例?
口诀:空、单元素、极端、重复、负数/特殊字符
| 题型 | 必备样例 | 说明/目的 |
|---|---|---|
| 数组查找/哈希 | 正常用例;重复元素;负数;目标不存在/多解(看题目是否保证有解) | 覆盖哈希查找的关键分支 |
| 双指针/滑窗 | 已排序 & 未排序;窗口极小/极大;全不满足/全满足 | 检查左右边界更新是否正确 |
| 字符串 | 空串;单字符;大小写混合;含空格或标点;Unicode(了解即可) | 检验遍历与条件过滤 |
| 栈/队列 | 合法序列;非法但长度接近;嵌套深度很深 | 易错在出栈时机与匹配 |
| 二分 | 目标在头/尾;不存在;全相等;有重复的最左/最右 | 检查 mid & 边界收缩 |
| 动态规划 | n=0/1 的最小规模;最大规模;边界转移(如 0/负数) | 检验初值与转移式 |
| 链表 | 空链;单节点;环/无环(看题);头尾操作 | 指针移动与返回头结点 |
| 树 | 空树;单节点;只有左/右子树;完全/不完全 | 递归 base case 是否健壮 |
Python高效刷题题单:
因为我离面试的时间很紧,我就先给自己制定了60道题来争取快速过面试。
这些题目主要都是leetcode 100和leetcode 75里面的。
我的刷题策略是:
- 看懂题目描述 + 示例,尝试用自己的话说出:问题的本质是什么?
- 自己手写几个测试小例子(不看答案),以明确输入输出、核心目标。
- 尝试解决问题(哪怕只使用暴力算法解决)。
- 再看一下较优解或最优解,更正一下我们的解法。
📘 一、基础算法与数据结构(20题)
重点是熟悉常用模板,能灵活套用。
| 分类 | 代表题目 | 说明 |
|---|---|---|
| 数组与双指针 | 1. 两数之和 26. 删除有序数组重复项 283. 移动零 | 高频基础 |
| 字符串 | 3. 无重复字符的最长子串 49. 字母异位词分组 5. 最长回文子串 | 高频 |
| 栈与队列 | 20. 有效的括号 155. 最小栈 739. 每日温度 | 栈思想典型 |
| 链表 | 21. 合并两个有序链表 141. 环形链表 206. 反转链表 | 经典题 |
| 哈希 | 242. 有效的字母异位词 560. 和为K的子数组 | 哈希思维入门 |
📗 二、进阶算法(20题)
考察你对算法思维的理解深度。
| 分类 | 代表题目 | 说明 |
|---|---|---|
| 二分搜索 | 33. 搜索旋转排序数组 153. 寻找旋转排序数组中的最小值 | 模板题 |
| 递归与回溯 | 46. 全排列 78. 子集 39. 组合总和 | DFS模板 |
| 动态规划 | 70. 爬楼梯 198. 打家劫舍 322. 零钱兑换 | DP基础 |
| 二叉树 | 94. 中序遍历 104. 二叉树的最大深度 102. 层序遍历 | 基础+BFS/DFS |
| 贪心算法 | 55. 跳跃游戏 45. 跳跃游戏II | 高频公司题 |
📙 三、综合与高频(20题)
公司机试面试中常见。
| 分类 | 代表题目 | 说明 |
|---|---|---|
| 滑动窗口 | 76. 最小覆盖子串 567. 字符串的排列 | 高频难题 |
| 前缀和 / 差分 | 238. 除自身以外的数组乘积 560. 和为K的子数组 | 高频技巧 |
| 图 | 200. 岛屿数量 207. 课程表 | BFS/DFS理解 |
| 堆与优先队列 | 215. 数组中的第K大元素 347. 前K个高频元素 | 公司常考 |
| 综合模拟 | 42. 接雨水 94. 二叉树中序遍历 | 面试压轴题 |