简介:LeetCode全题目解答汇总包,专为算法学习者、面试备战者与希望夯实编程功底的开发者准备。资源按题目系统整理,覆盖排序、查找、动态规划、图论、回溯、贪心、字符串处理等主流算法类型,同时涉及链表、树、堆、哈希表等高频数据结构;每道题都给出题目描述、输入输出格式、示例测试用例、多语言代码实现与解题思路,并附时间、空间复杂度分析,便于对照理解和举一反三。压缩包共972个文件,以Markdown解题文档(497个)、Java实现代码(259个)和TXT说明笔记(192个)为主体,辅以PDF题解、HTML页面等材料,整体仅12.54MB,结构清晰、查找方便。目前已有3930人学习下载,适合按知识点逐类攻克或面试前集中刷题,是兼顾广度与深度的算法学习资料。
1. 有一份「Leetcode所有题目和解答.zip」意味着什么
LeetCode 刷题超过一个月,你就会承认:卡题的时候,真正让你心里有底的不是再多想十分钟,而是手边有一份可靠的全量题解。这份压缩包解决的是算法刷题里最耗时的查找环节——离线环境下按题号检索、按难度回顾、打开完整代码与复杂度分析,不用在多个题解站点之间来回翻页。它最合适的人群有三类:准备算法面试的在职开发者、想系统过一遍数据结构的进阶新手,以及需要给学员讲题的带队者。它解决的是效率问题,不是替代思考。这两个边界一开始划清楚,后面所有用法都顺了。
2. 拆开题解包:目录树、文件结构与多语言解答的组织逻辑
在把压缩包变成工具之前,先得知道它里面是什么结构。LeetCode 题解包的来源不同,组织方式也有差别——按题号展开、按标签展开、按难度三级分类都有。但最稳定、最适合二次开发的,是「按题号展开的一题一目录」结构。
2.1 按题号展开的目录树:一题一目录是底线
压缩包解压后,根目录下通常是这样的:
LeetCode-All/ ├── 0001-two-sum/ ├── 0003-longest-substring-without-repeating-characters/ ├── 0015-three-sum/ ├── 0042-trapping-rain-water/ ├── 0084-largest-rectangle-in-histogram/ └── ...每个目录名由「四位数补零题号 + 英文短横线别名」组成。这种命名有实际好处:题号在平台上几乎不变,标签会改、难度会调、题目描述会更新,但题号是稳定标识。目录名本身也自带检索价值——你搜0042,或者搜trapping-rain-water,都能命中同一个目标。
另一种常见的组织方式是按标签分顶层目录,比如dynamic-programming/、binary-search/、tree/。这种结构对想把题解包当工具用的人不太友好:一道题往往挂三四个标签,存哪个目录都有理由,复制多份又占空间。后面所有脚本和操作,默认按「按题号展开」的结构走。如果你的压缩包是标签结构,第一步建议先写个脚本把题解统一归位成按编号的目录,别急着刷题。
2.2 单题目录里的文件分工:题面、思路、复杂度与代码各司其职
打开任意一个题目录,常见文件分工如下:
| 文件名 | 内容 | 使用建议 |
|---|---|---|
README.md | 题目描述、示例、约束条件 | 先读它,不要上来就看代码 |
Approach.md | 解题思路、关键推导、复杂度分析 | 也常命名为思路.md,属于必读 |
solution.py | Python 实现,通常有暴力解与优化解 | 本地跑通再提交 |
solution.cpp | C++ 实现,更强调边界与性能 | 需要本机有编译环境 |
solution.java | Java 实现 | 主要看类与接口设计 |
先读README.md,再读Approach.md,最后看代码——这个顺序比直接翻代码高效很多。如果某道题有两个 Python 文件,通常命名solution.py和solution_optimized.py,分别对应易读版本和高效版本。个别包里还有notes.txt,记录的是整理者当时的踩坑点,比如「前缀和方案会爆 int」这类备注,这类文件往往比代码本身更值钱。
单份题解文件的典型代码长这样:
# solution.py from typing import List class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: seen = {} for i, num in enumerate(nums): complement = target - num if complement in seen: return [seen[complement], i] seen[num] = i return []逻辑说明:seen字典保存「数值到下标」的映射,每遍历一个数先查 complement 是否已经出现过,命中就直接返回两个下标。参数说明:nums是输入数组,target是目标和,返回值是长度为 2 的下标列表。这段代码时间复杂度 O(n),空间复杂度 O(n),是经典的哈希表解法。读题解时先确认这一类核心思路,再看具体写法,比逐行读代码有效得多。
2.3 多语言解答的取舍:Python 看思路,C++ 看边界
大部分题解包的语言分布是 Python 为主、C++ 次之、Java 再次之。这个分布不是随便排的:
Python 代码最短,适合看思路;C++ 代码强调内存边界和类型处理,比如整型溢出、vector 的引用传递;Java 介于两者之间,有时会牺牲可读性。我的阅读策略是:一道题的思路理解只看 Python 版;确认复杂度和边界条件时,扫一遍 C++ 版注释;如果面试需要 Java 手写,再对照 Java 代码过一遍语法细节。这样一份题解包才能在复习、自测、模拟面试三种场景下分别发挥价值。
3. 把题解包变成刷题工作台:索引脚本、快速打开与三步对照练习
题解包的价值怎么衡量?如果你打开它要在一层层目录里翻 15 分钟,这个价值已经被消耗了一半。所以我拿到压缩包之后做的第一件事不是刷题,而是写一个索引脚本,给自己铺一条从「想做题」到「看到对应题解」的管道。
3.1 用 Python 建本地索引:题号、别名、路径一次理顺
在解压后的根目录放一个build_index.py,跑一次生成index.json:
import os import json BASE = "LeetCode-All" OUT = "index.json" def build_index(): entries = [] for name in os.listdir(BASE): if len(name) < 5 or not name[:4].isdigit(): continue # 跳过非题目目录 path = os.path.join(BASE, name) if not os.path.isdir(path): continue # 目录名形如 0001-two-sum,拆成编号与别名 if "-" in name: slug = name.split("-", 1)[1] else: slug = "" entries.append({ "id": int(name[:4]), "slug": slug, "full": name, "path": path, }) entries.sort(key=lambda x: x["id"]) with open(OUT, "w", encoding="utf-8") as f: json.dump(entries, f, ensure_ascii=False, indent=2) print(f"索引完成,共 {len(entries)} 个题目录") if __name__ == "__main__": build_index()逻辑说明:脚本扫描根目录,用isdigit()判断前四位是否为数字,过滤掉assets、scripts这类非题目目录;再把目录名拆成id和slug,按题号排序写入index.json。后续不管要做检索、打开还是标记,都只读这个文件,不再遍历磁盘。参数说明:BASE指向题解包根目录,OUT是索引输出位置,两者都可以改成绝对路径。ensure_ascii=False让 JSON 里的中文直接显示,indent=2只是便于人工检查。
索引生成后,命令行检索可以这样用:
python -c "import json; d=json.load(open('index.json', encoding='utf-8')); [print(x['id'], x['slug'], x['path']) for x in d if 'dp' in x['slug']]"这里'dp' in x['slug']是子串匹配,能粗略捞出与动态规划相关的题,但也会误伤一些别名里带dp的题,所以只用作快速过滤。精确的主题归类,留给第 4 章的专题地图去处理。
3.2 终端一键打开:lg 命令的 bash 封装
频繁在文件管理器里一层层点进目录很碎。我把打开操作封装成lg,配合 VSCode 直接跳到目标目录:
lg() { python3 - "$1" <<'PY' import json, subprocess, sys target = sys.argv[1] entries = json.load(open("index.json", encoding="utf-8")) hit = None if target.isdigit(): hit = next((e for e in entries if e["id"] == int(target)), None) else: hit = next((e for e in entries if target.lower() in e["slug"].lower()), None) if hit: print("打开: " + hit["full"]) subprocess.run(["code", hit["path"]]) else: print("未找到: " + target) sys.exit(1) PY }逻辑说明:函数入口就一个参数,纯数字按题号精确匹配,带字母的按别名子串匹配;命中后调用code命令打开目录,VSCode 会直接把整个文件夹放进侧边栏。参数说明:index.json的相对路径依赖终端当前目录,建议自己改成绝对路径,或者把终端固定停在题解包根目录再用。外部依赖只有code命令,它来自 VSCode 安装时自动加入 PATH 的入口;没装 VSCode,可以直接替换成open或explorer。
3.3 对照练习三步法:先默写、再对比、最后关掉重写
工具就位之后,刷题流程要从「看题解」切换到「对照练习」。我自己用了相当长一段时间的流程是这样的:
第一步:独立写 30 分钟。拿到一道题,先不打开题解目录,新建一个solution_my.py,硬着头皮写。写不出来就空着,把卡住的点记在文件顶部注释里。
第二步:打开参考,做差异对比。用lg 0042打开题解目录后,重点不是看代码能不能跑通,而是对比三个点:你的遍历顺序和题解是否一致、边界处理有没有漏、空间复杂度差在哪个数据结构选择上。把结论写进目录下的my_notes.md。
第三步:合上题解,重新 AC 一遍。关掉题解目录,30 分钟内从零写出提交版本。这一遍还能依赖记忆是通过的底线线;第二周再抽同一道题复写,还需要翻答案,这道题就进错题队列。
这套方法执行一个月之后,和纯看题解的差距会很明显。差别在于:看答案时你会跳过自己最薄弱的能力——构建解题路径的能力,而重写动作会把这份能力强行拉回来。
4. 把题解包变成私有资源库:算法模板、错题复习与专题地图
原包只读的题目解答只能算公共资源;在上面叠加自己的笔记和索引,才叫私有资源库。我的习惯是先把压缩包复制一份作为备份,日常在副本上操作,脚本写坏了也能重新解压复原。
4.1 提炼模板:把高频解法沉淀成可默写的二分骨架
题解包里的题很多,但真正值得背下来的骨架数量很有限。以二分法为例,不同题解对边界的处理风格差异很大,我从中固定了一套默认模板:
def lower_bound(nums, target): """返回第一个 >= target 的下标;不存在则返回 len(nums)""" left, right = 0, len(nums) while left < right: mid = left + (right - left) // 2 if nums[mid] < target: left = mid + 1 else: right = mid return left逻辑说明:right = len(nums)而不是len(nums) - 1,是为了让模板天然覆盖目标值比数组中所有元素都大的情况,这时的返回值是数组长度,调用方可以直接判断没找到。while left < right退出时区间收敛到单个点,这个点就是答案。mid取left + (right - left) // 2,避免(left + right) // 2在数组很大时溢出。参数说明:如果你想要的是「第一个大于 target 的下标」,把比较里的<改成<=,其他部分不动。这套模板能覆盖大部分二分题,遇到变体时再针对边界条件做局部调整。
有了统一模板之后,再看题解包里的二分题,注意力就可以放在「这道题为什么让模板变形」上,而不是被每份代码的不同风格带跑。
4.2 错题复习队列:一行题号加一个随机抽取脚本
错题本如果搞成一个重工具,基本坚持不下去。我用的方案是一个纯文本文件加几行 Python:
# review.txt # 格式:每行一个题号,解题没通过的放这里 0042 0072 0115复习队列脚本:
import random REVIEW_FILE = "review.txt" def load_review(): ids = [] with open(REVIEW_FILE, encoding="utf-8") as f: for line in f: line = line.strip() if line.isdigit(): ids.append(int(line)) return ids def pick_daily(ids, k=3): return random.sample(ids, min(k, len(ids))) if __name__ == "__main__": queue = pick_daily(load_review()) print("今天复习:", " ".join(f"{i:04d}" for i in queue))逻辑说明:题号每行一个,脚本随机抽取,避免每次都复习同一批旧题。固定的k=3让每天的复习量保持稳定。参数说明:pick_daily的k按空闲时间调整,比较忙时改成 1,周末改成 5;复习完成后把题号从review.txt删掉,保留在另一份finished.txt里作为历史记录。错题标记的核心规则是:题目做不出来时才写进来,而不是看完题解就写。如果看一份答案就记一道错题,第二天开始你就是在给自己罗列心理安慰。
4.3 专题地图:绕过目录结构,按主题把散题串起来
题号目录最大的弱点是缺少主题维度。我的办法是维护一份topics.md,把散在同一目录树里的同类题归到一起。具体操作分两步。
第一步,先用 grep 搜索题解包里的思路文档:
grep -rl "monotonic stack" LeetCode-All --include="*.md" | head -20逻辑说明:-rl表示只列出包含匹配内容的文件名,--include="*.md"把范围限定在说明文档里,避免被代码注释干扰结果。第二步,对命中的题号逐一确认,写入topics.md:
## 单调栈 - 0042: 接雨水,左右边界经典题 - 0084: 柱状图最大矩形,最小高度变体 - 0239: 滑动窗口最大值,单调队列同类技巧这样刷题时按主题走,复习时按题号走,两个维度互不干扰,也不需要改动原始目录结构。遇到热门百题这类常被翻牌的清单时,我也在topics.md里单独加了一节,把重复出现在多个专题里的题标出来,这些题往往就是核心中的核心。
5. 使用题解包的五个常见问题与排查清单
工具再好,坑永远在下一步。下面五条都是实际使用中踩过的翻车记录,按「现象 → 原因 → 解决」的方式列出来,方便你对照排查。
5.1 解压报错 eocd 缺失或只有部分文件
现象:解压到 60% 时提示文件结束,或者直接报invalid zip archive: could not find eocd。
原因:压缩包下载不完整,或者网络传输被中断。EOCD(End of Central Directory)记录在文件末尾,它缺失说明文件没收尾,解压工具无法生成完整目录结构。
解决:先校验文件完整性。Windows 下用 7-Zip 右键「测试压缩包」,Linux 下执行unzip -t 文件名.zip或zip -T 文件名.zip。不完整就重新拿一份,不要用残包硬解。容易忽略的另一件事:多分卷包要放在同一目录,后缀齐全后再解压,少一卷都会报同样的错。
提示:依赖题解包运行的自定义脚本,都该把「先验证压缩包完整」放进第一步,这是花过一次大时间后的血泪经验。
5.2 题号对得上,题目描述和示例却对不上
现象:打开0033-search-in-rotated-sorted-array,发现 README 里的示例输出和在线题库不一样。
原因:平台会不定期修正题目,比如改示例、增强约束、调整边界描述,而题解包停留在某个时间点,不会自动跟随更新。
解决:以在线题库为准,题解包只提供算法角度参考。代码里如果有输入解析逻辑,通常还需要改成当前题目的格式。链表的序列化方式、树的null表示在不同版本里可能不同,这时只保留解法函数核心部分,输入处理直接重写,不要心存侥幸。
5.3 原样复制题解,粘贴过去却编译失败
现象:本地跑得好好的题解,原样粘到在线编辑器里报错,常见提示是List未定义,或者函数签名对不上。
原因:本地代码文件里有from typing import List这类导入语句,而在线编辑器在部分语言版本里不会自动注入;另一个常见原因是题解更新时间较早,函数签名参数名和当前环境不一致。
解决:动手之前先确认两件事:当前题号对应的在线函数签名,以及文件里缺哪些类型导入。我习惯把题解文件统一补一遍from typing import List, Optional,涉及链表或树节点时,提前写好自己的ListNode、TreeNode定义。本地跑通不等于粘贴即用,环境差异本来就是刷题实务的一部分。
5.4 中文标题和文档解压后乱码
现象:解压之后README.md里的中文变成乱码,文件名也出现不规则字符。
原因:压缩包内编码是 UTF-8,部分 Windows 解压工具用本地代码页去解析文件名和文本,造成错位。
解决:换用支持存储编码的解压工具,或者单独设置解压选项。已经乱码的文件逆向恢复比较麻烦,我建议不要在原包上反复折腾,而是在本地新建一个笔记目录,把乱码文件内容读取出来转移到新文件。重要的是内容本身,不是文件名那串字符。
5.5 把刷题变成看题:题解包太好用反而害人
现象:刷了三周,每道题都能立刻看懂题解,但闭卷写新题时依旧卡壳。
原因:这是五个问题里最重要的一条。「看懂题解」和「会做题」是两条完全不同的回路:前者是被动接收,后者是主动构建。题解包太方便,会让人不自觉地停留在舒适区里只看不写。
解决:把「先写后看」定成硬约束。一道题动手前至少要尝试 25 分钟,写不出再打开题解;一份题解看完后,24 小时内必须关掉答案重新实现一遍,否则这道题不进完成列表。这样题解包就从一个「答案大全」退回到「教练」的角色,训练节奏由你控制,而不是被资源带着走。
6. 自测技巧:用「挖空法」检验一道题到底吃透没有
一道题做完、提交通过,并不代表它属于你了。真正的验证时机是两个星期以后能不能复现出来。为了让自己这种健忘体质拿到一个相对客观的答案,我用的是挖空法。
挖空法很直接:把题解文件复制出来,把核心代码行替换成TODO,只保留函数签名、注释和输入输出骨架,然后在不看原题的条件下把这些坑补回来。这个动作比默写整道题省力,又比看题解有效得多。
6.1 挖空脚本怎么改:按题型切换 pattern 集
import re def blank_out(src, dst, patterns): with open(src, encoding="utf-8") as f: lines = f.readlines() with open(dst, "w", encoding="utf-8") as f: for line in lines: stripped = line.strip() # 只挖掉逻辑行,保留 import、函数签名与注释 if any(p in stripped for p in patterns) and not stripped.startswith("#"): line = re.sub(r"[A-Za-z_][A-Za-z0-9_]*", "TODO", line) f.write(line) if __name__ == "__main__": blank_out( "solution.py", "practice_dp.py", ["dp[", "if ", "return "] )逻辑说明:patterns里三个关键词覆盖大多数 DP 题的核心逻辑,if命中边界条件,return命中转移结果,dp[命中状态转移本身。替换用的是正则词法匹配,不会把注释里的单词改掉。参数说明:建议按题型维护不同 pattern 集,二分题用["mid", "while ", "return "],链表题用["cur", "next", "while "],针对性强一些,挖出来的练习文件更有训练价值。
6.2 挖空练习的完整流程与判定标准
操作顺序如下:第一步,选定一周内 AC 的中等难度题;第二步,运行脚本生成practice_dp.py;第三步,关闭所有题解目录,打开挖空文件,把TODO补成可运行的代码;第四步,补完后跑测试,再和原始题解对比复杂度和写法差异。
判定标准是:补出来的代码和原解完全一致,说明你已经内化了这条解法;补出不同写法且同样 AC,也算过关,顺手记一句差异;连续几道都补不回来,就把题号放回第 4 章的review.txt,延迟推进新题。
从那以后,我每道中高难度的题都会在 AC 当天顺手跑一遍挖空脚本,把记忆固化从「看过就算」改成了「补得出才算」,手感明显比裸刷稳定得多。希望这个技巧帮到你。
本文还有配套的精品资源,点击获取