首页 / 资讯中心 / 文章详情

Python版LeetCode题解合集:可运行代码与专题分类提升刷题效率

Python版LeetCode题解合集:可运行代码与专题分类提升刷题效率 ★ FEATURED ARTICLE
简介一套覆盖力扣全部题目的 Python 解答合集面向准备算法面试、提升编程能力的 Python 开发者。题目由浅入深涵盖数组、链表、栈、队列、哈希表、二叉树、图论以及动态规划、回溯、贪心等经典算法模块有助于系统构建算法知识体系。资源共1160个文件包含579个可直接运行的.py源码与580个.md解题说明另附.gitignore文件压缩包仅544KB体量紧凑但内容完整按题目序号组织便于快速定位任意题目的代码和解析。目前已有587人学习适合日常刷题对照、解法复盘和面试前集中训练。通过研读这些解答可以掌握 Python 内置 list、dict、set 等数据结构熟悉 itertools、collections、heapq 等库在排列组合、计数、堆操作中的灵活用法同时理解不同解法的时空复杂度与适用边界进而提升逻辑思维和工程实现能力为技术面试和长远职业发展打下坚实基础。1. 一套Python版的LeetCode题解合集究竟能给你省下什么很多人在刷LeetCode时都有过这样的体验题解看了几十篇收藏夹里堆满了链接真到自己上手写时连一个“输入链表如何构造”都要翻半天。如果手头有一套按知识点整理、带完整可运行代码和测试用例的Python题解情况会完全不同。这套“leetcode全套解答python版本”解决的核心问题不是替你刷题而是把“看懂思路”到“跑通代码”之间那段最磨人的路铺平。它的价值体现在三处一是省去从零搭建环境、组织代码结构的时间二是每道题都有可直接运行的Python脚本方便你改参数、加测试、对比不同写法三是题解按数据结构和算法专题分类能直接当做一份检索手册用。适合的人群很明确准备校招或社招算法面试的开发者、转行Python想补数据结构基础的初学者、以及需要一份代码模板应对竞赛的熟手。与其收藏一百篇碎片文章不如直接在一套能跑的代码里做增量修改。2. 一套能落地的题解合集先搞清它该有的样子2.1 为什么Python是刷LeetCode的主流选择语法开销小抽象层次高Python在LeetCode生态里的地位从讨论区提交占比就能看出来。它最大的优势是“把精力留给算法本身”链表的定义、二叉树的遍历、堆的调整在Python里往往只用几行而在C或Java里需要同步管理指针和类型。对面试场景来说这直接意味着能更快写出正确代码把时间花在边界条件和复杂度分析上。以广度和深度优先搜索为例Python的deque和递归写法都能把代码压到很短。再看动态规划二维数组的初始化和状态转移Python的列表推导式写起来直觉感很强。还有一点容易被低估Python的heapq、functools.lru_cache、itertools这些标准库本身就是“免费源码”能帮你省下大量造轮子的时间。LeetCode热门100题里有很大一部分用Python可以在二十行左右完成核心逻辑。这套题解合集的定位就建立在Python的这些特性上每道题不只是贴一份AC代码而是给出可运行文件、测试入口、以及针对Python特性的写法说明。这样你复现时不需要改任何环境配置复制进本地就能跑。2.2 从一道题看合集标准爱吃香蕉的狒狒完整拆解LeetCode 073题“爱吃香蕉的狒狒”是二分查找的经典应用也经常被拿来考察“怎么把直觉问题转成二分判定”。一道合格的Python题解至少要包含三样东西题意建模、二分边界的写法、以及一个能直接跑的测试框架。import math from typing import List def min_eating_speed(piles: List[int], h: int) - int: 二分查找最小吃香蕉速度。 速度下限是1上限是max(piles)——再快也没意义。 判定函数 check(speed) 检查该速度下能否在 h 小时内吃完。 def check(speed: int) - bool: # 每堆香蕉需要 ceil(pile / speed) 小时注意向上取整 hours sum((pile speed - 1) // speed for pile in piles) return hours h left, right 1, max(piles) while left right: mid (left right) // 2 if check(mid): right mid else: left mid 1 return left # 测试用例直接在脚本里跑不需要OJ if __name__ __main__: assert min_eating_speed([3, 6, 7, 11], 8) 4 assert min_eating_speed([30, 11, 23, 4, 20], 5) 30 assert min_eating_speed([30, 11, 23, 4, 20], 6) 23 print(全部测试通过)check函数是这套解法的核心它的作用是把“能不能在h小时内吃完”转成一个纯数值判定。这里计算小时数用了(pile speed - 1) // speed代替math.ceil是因为整数运算在大量调用时更快也避免引入浮点误差。二分循环的退出条件是left right当check(mid)为真时让right mid这样收敛到最后left就是最小可行速度。注意这里不能写成right mid - 1否则会跳过正确答案。这套题解合集的每一道题都按这个标准来组织先写清思路注释再给可运行的完整代码最后挂上几个边界测试用例。你在本地跑通这题后再去看同类的875、1482、1011会发现二分判定的模板几乎可以平移。2.3 适合长时间维护的目录结构按专题分流不按题号堆叠一套题解不能是几百个文件平铺在一个文件夹里那样检索成本极高。常见的做法是按数据结构和算法专题分目录而不是按题号。我的推荐结构是这样leetcode_python/ ├── 01_array/ # 数组与双指针 │ ├── 001_two_sum.py │ ├── 015_three_sum.py │ └── test_all.py ├── 02_linked_list/ # 链表 ├── 03_binary_tree/ # 二叉树与递归 ├── 04_dp/ # 动态规划 ├── 05_binary_search/ # 二分查找 ├── 06_graph/ # 图与搜索 ├── 07_heap_stack/ # 堆与单调栈 ├── common/ # 公共数据结构与工具函数 │ ├── list_node.py │ └── tree_node.py └── README.md每个专题目录下文件名统一为题号_英文短名.py便于排序和识别。common目录放的是自定义数据结构的定义比如LeetCode里ListNode和TreeNode在本地并不存在需要自己补上。这样设计的直接好处是当你刷到“用堆解决Top K问题”时直接进07_heap_stack目录按题号找到对应代码改改输入就能验证。如果你打算长期维护这套题解README用表格记录每道题的状态是值得的。状态至少三列题号、解法标签如“二分贪心”、是否已写题解。这样不会刷到一半忘记哪些是重点题。3. 在本地跑通这套Python代码环境、数据结构和测试入口3.1 从零搭建运行环境Python版本和包管理的选择这套题解合集的代码依赖很少这也是Python题解的最大优点——绝大多数标准库自带就够用不需要额外装第三方包。如果你从零开始下面是环境准备的标准步骤# 1. 检查Python版本题解基于3.8语法建议3.10以上 python --version # 2. 创建虚拟环境避免污染全局Python python -m venv leetcode_env # 3. 激活虚拟环境 # Windows: leetcode_env\Scripts\activate # macOS/Linux: source leetcode_env/bin/activate # 4. 验证pip和基础库 pip list虚拟环境是必须做的一件事不需要犹豫。原因很实际很多机器上全局Python装了各种项目依赖版本互相干扰是常态。venv之后题解代码里的import只会用到标准库——math、collections、heapq、functools这些都不用额外安装。唯一可能用到第三方库的场景是画图辅助分析比如用matplotlib把动态规划的转移过程可视化这种需求按需pip install即可不必一开始全装。环境变量的配置在Windows下安装Python时勾选“Add Python to PATH”就能省去后续手工配置的麻烦。macOS/Linux用户一般自带了Python3只需要用python3命令区分版本。3.2 自己实现链表和树节点复现OJ环境的必备工具LeetCode平台在后台已经替你定义好了ListNode和TreeNode但在本地这两个类并不存在。一套好用的题解合集必须在公共模块里把这些数据结构补齐这样所有题目才能“开箱即跑”。下面是common目录下的核心实现# common/list_node.py from typing import Optional, List class ListNode: 单链表节点与LeetCode定义保持一致。 def __init__(self, val: int 0, next: Optional[ListNode] None): self.val val self.next next def build_linked_list(nums: List[int]) - Optional[ListNode]: 从列表构造链表用于本地测试。 dummy ListNode() current dummy for num in nums: current.next ListNode(num) current current.next return dummy.next def linked_list_to_list(head: Optional[ListNode]) - List[int]: 把链表转回列表方便断言结果。 result [] while head: result.append(head.val) head head.next return result# common/tree_node.py from typing import Optional, List class TreeNode: 二叉树节点。 def __init__(self, val: int 0, left: Optional[TreeNode] None, right: Optional[TreeNode] None): self.val val self.left left self.right right def build_tree_from_list(data: List[Optional[int]]) - Optional[TreeNode]: 按层序遍历序列构造二叉树输入的None表示空节点。 if not data: return None root TreeNode(data[0]) queue [root] index 1 while queue and index len(data): node queue.pop(0) if data[index] is not None: node.left TreeNode(data[index]) queue.append(node.left) index 1 if index len(data) and data[index] is not None: node.right TreeNode(data[index]) queue.append(node.right) index 1 return root构造链表的dummy节点是这里最值得注意的写法。如果不设一个虚拟头节点插入第一个元素时就得单独写分支代码会丑且容易漏。build_tree_from_list则完全遵循LeetCode的层序序列化约定——数组里None的位置就是空子树这样你在平台看到的测试用例输入可以直接复制进本地。有了这两个工具函数题解代码里只要from common import list_node, tree_node就能构造任意测试数据。这也是整套合集能“跑起来”的前提条件。3.3 带测试入口的题解模板让你改完参数立刻看到结果一套题解如果只有solution函数、没有测试入口你每次都要自己写调用代码时间一长就不想用了。把测试入口直接嵌进每个题解文件的if __name__ __main__块里是维护成本最低的验证方式。# 04_dp/070_climbing_stairs.py from typing import List def climb_stairs(n: int) - int: 爬楼梯问题经典的斐波那契变形。 用滚动变量代替整个DP数组空间O(1)。 if n 2: return n prev, curr 1, 2 for _ in range(3, n 1): prev, curr curr, prev curr return curr if __name__ __main__: test_cases [ (2, 2), (3, 3), (10, 89), ] for n, expected in test_cases: result climb_stairs(n) assert result expected, fn{n}, 期望{expected}, 实际{result} print(所有测试用例通过)这段代码体现了题解集合格局的三个要点一是解法本身用滚动变量优化了空间这比直接开一个n1长度的数组更值得学二是assert断言能把错误精确到具体输入上比print肉眼比对结果可靠得多三是测试用例里覆盖了n2的边界和中等规模输入。当你尝试修改算法逻辑时跑一次脚本就能立刻知道改对没有。这套“一题一脚本、带测试入口”的题解组织方式还有一个很容易被忽略的好处它能配合自动化统计脚本批量检查哪些题解还能通过全部测试。4. 把题解变成自己的东西配置、刷题路线和自动化脚本4.1 按数据结构和算法优先级排刷题顺序题解合集的价值上限取决于你怎么用它。LeetCode热门的题目有一千多道但和面试强相关的核心题大约两百道。我建议按专题切块而不是按题号顺序刷先数组和哈希表再双指针和滑动窗口然后二叉树和递归接着是二分查找和堆最后才是动态规划和图论。这样排的原因很直接前几个专题能帮你建立“把暴力解法优化到线性复杂度”的基本功二叉树则是练习递归思维的最佳载体而动态规划和图论需要前面这些基础打底。很多人在DP上卡住回头去看往往是递归和状态定义的基本功不扎实。# 一个简单的每日刷题统计脚本按目录统计题解数量和完成度 #! /bin/bash echo 当前题解总数 find . -name *.py ! -path ./common/* | wc -l echo 按专题统计 for dir in 0*/; do count$(find $dir -name *.py | wc -l) echo $dir : $count 题 done这个脚本不复杂但足以让你一眼看清每个专题的覆盖情况。如果07_heap_stack里只有三两题说明这块是你的短板接下来该集中补这里的题。4.2 用pytest做批量回归改代码不怕改坏旧题解题解维护时间长了你难免会想回头优化某道题的写法。但优化可能引入新bug而且只影响那道题本身。这时用pytest做批量回归测试是保住整套合集质量的底线。# test_all.py放在专题目录下例如 03_binary_tree/ import sys import os sys.path.insert(0, os.path.dirname(__file__) /..) from common.tree_node import build_tree_from_list from 104_max_depth import max_depth def test_max_depth_basic(): root build_tree_from_list([3, 9, 20, None, None, 15, 7]) assert max_depth(root) 3 def test_max_depth_empty(): assert max_depth(None) 0 def test_max_depth_single(): root build_tree_from_list([1]) assert max_depth(root) 1在专题目录下执行python -m pytest test_all.py -v就能看到每道题解的通过状态。这个做法的核心价值是“防止回归”——你改进了一道题的解法不会在不知情的情况下破坏另一道依赖相同数据结构的题。sys.path.insert这行是必要的它让测试文件能引用到上一级的common目录。如果没有pytest环境用python -m unittest做同样的事也完全可行标准库自带。选择pytest只是因为它报错信息更直观参数化测试写起来更简洁。4.3 从题解到模板提炼自己的算法代码骨架题解看多了以后你会发现很多题的代码结构高度相似。二分查找有模板树的遍历有模板单调栈有模板。从题解里提炼模板再通过套模板快速解新题是刷题水平从“会做”到“熟练”的分水岭。# common/templates.py from typing import List, Callable def binary_search_template(nums: List[int], condition: Callable[[int], bool]) - int: 二分查找通用模板。 condition(mid) 在满足条件时返回 True查找第一个满足条件的位置。 核心不变式: condition(left) 恒为 False, condition(right) 恒为 True left, right -1, len(nums) while right - left 1: mid (left right) // 2 if condition(mid): right mid else: left mid return right这个模板的边界处理比传统left right写法更不容易出错。它的不变式是left永远不满足条件right永远满足条件循环结束时right就是答案。用这个模板做爱吃香蕉的狒狒条件函数换成hours h即可连边界都不用额外思考。有价值的模板不需要多二分、快排、树的迭代遍历、单调栈、并查集这五个就够覆盖面试的大部分题型了。每个模板配上两三个经典题作为锚点要远比收藏几百份题解有效——因为模板是你自己提炼过的你已经理解它为什么长这样。5. 避坑指南题解复现路上的五个常见问题5.1 环境配置后import失败路径和虚拟环境没生效现象跑from common.tree_node import build_tree_from_list时报错ModuleNotFoundError: No module named common。原因当前工作目录和common文件夹不在同一个层级或者虚拟环境激活后没有在正确的项目根目录下运行python。解决先pwd确认自己处在leetcode_python根目录再source leetcode_env/bin/activate激活环境。如果用的是IDE自带终端记得重启终端让环境变量生效。5.2 本地跑通但提交超时递归转迭代被忽略了现象树的先序遍历本地测试正常提交LeetCode提示Time Limit Exceeded。原因深度很大的链式树比如每层只有左子树会让递归栈深度达到数万层Python的递归深度默认上限只有1000超了直接爆栈。解决把递归写法改成显式栈的迭代写法或者用functools.lru_cache做记忆化剪枝。这套题解合集的代码里凡是标注“迭代版”的都要优先看面试时主动写迭代版也更有区分度。5.3 本地测试通过但提交报错输入类型被改掉了现象本地把[1,2,3]转成了链表提交后却报AttributeError: list object has no attribute val。原因LeetCode的函数签名里链表参数已经是构造好的ListNode不需要再用工具函数转换。很多人习惯了本地构造数据到OJ上忘记删掉转换代码。解决在题解里加注释区分“平台输入”和“本地测试输入”。标准的做法是solution函数直接处理ListNode类型本地测试入口里才调用build_linked_list。5.4 assert起了副作用测试用例改动了原始数据现象多跑几次测试后结果变得不稳定有时通过有时失败。原因某些函数直接修改了传入的链表或数组比如head.next head.next.next跑完一次后原始数据被破坏第二次测试拿到的就是残缺输入。解决测试用例里每次都重新构造输入不要复用同一个对象。这也是一套合格题解“可重复运行”的基本前提。5.5 周赛题解看不懂变量命名和内置函数太“炫技”现象看某些题解时被zip、enumerate、列表推导式的多层嵌套绕晕感觉自己Python白学了。原因题解作者为了缩短代码把多个逻辑压缩在一行里牺牲了可读性——这恰恰是面试的大忌。解决以“能讲清楚”为第一标准。多写几行普通循环完全没关系面试官看的是思路。这题解合集也遵循这个原则宁可多写辅助函数不在一个表达式里塞三个逻辑层。6. 把刷题变成系统工程三个进阶技巧和我的验证习惯真正拉开刷题效率差距的不是单题解法背得多熟而是有没有一套自己的“解题工作流”。“工作流”的第一步是做题型标签。LeetCode热门100题覆盖面足够广但你在题解合集里每做完一题都应该给它打上两个标签一个是数据结构栈、堆、树、图一个是算法范式贪心、DP、二分、回溯。后续复习时按标签聚合比按题号顺序过一遍效率高得多。第二步是设置重刷周期三天后重刷标记为“生疏”的题两周后再刷一遍一个月后只刷错题。这套节奏比“每天新做三题”更符合记忆曲线的规律。第三步是建立代码复杂度清单。很多人能写出AC代码但被问“时间复杂度和空间复杂度分别是多少”就卡住。我的习惯是每题题解的末尾用一行注释写上“时间复杂度O(n)空间复杂度O(1)瓶颈在xxx”。这样积累下来你会慢慢发现不同做法的取舍是体系化的而不是零散的。我个人的验证习惯是每完成一个新的专题就删除该专题下所有测试用例再重写一遍——不是全删而是把函数实现的代码遮住从注释和函数签名反向补全实现。这道工序很花时间但效果极好因为复查时能区分“真会”还是“背答案”。如果补不出来就回到题解对照在错误的位置做标记两周后再来一次。坚持几个专题后你会明显感觉到新题上手速度快了一个档次看题解时也能直接看出作者的代码有没有边界漏洞。一套Python版LeetCode题解合集本质上是一份能跑的笔记。它帮你省下的是重复整理环境、构造测试数据的体力活而理解算法、提炼模板、建立复习节奏仍然是只有你自己能完成的部分。希望这套方法和代码骨架能让你把精力花在真正值得花的地方——写出属于你自己的、讲得清楚的解法。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站