数据结构与算法之美 · 深度学习指南(细化样板)

作者:王争(前 Google 工程师)| 极客时间最经典算法课 真实结构:56 讲正文(含 10 讲算法实战)+ 4 期不定期福利 + 春节 7 天练 本指南按课程真实讲次提炼,融入每一讲的核心知识点 + 课程原案例 + 思考题,并标注了每讲「学完要能回答的问题」。


0. 这门课到底讲什么(课程自述)

课程开篇就点破了一件事:数据结构和算法解决的是「快」和「省」的问题——让代码跑得更快、更省存储空间。而王争老师反复强调的一句核心判断是:

「复杂度分析是整个算法学习的精髓,掌握了它,数据结构和算法的内容基本上就掌握了一半。」

所以这门课不是「背数据结构」,而是「建立一套分析问题、评估效率的思维模型」。学完的终极目标是——遇到任何系统,都能看出它底层用了什么数据结构和算法。


1. 模块一:开篇 + 复杂度分析(第 1–4 讲)

讲次核心知识点课程原案例 / 金句
01 为什么要学算法是内功,直接决定性能天花板;大厂面试必考「5 秒 vs 0.001 秒的差距,就是算法和不会算法的差距」
02 怎么高效学20 个知识点 + 10 个算法;边学边练边刷题抓住重点:线性表、树、图、排序、查找、哈希、字符串、贪心/分治/回溯/DP
03 复杂度分析(上)大 O 表示法;事后统计法两大局限(依赖环境、依赖数据规模)求 1+2+…+n 的代码:i9 比 i3 快、数据有序时排序「不用做任何操作」
04 复杂度分析(下)最好 / 最坏 / 平均 / 均摊 四种复杂度;均摊分析法数组插入扩容的「均摊」分析(偶尔一次 O(n),摊到每次仍是 O(1))

引发思考:

  1. 为什么「把代码跑一遍测时间」不能替代复杂度分析?(环境 + 数据规模两大局限)
  2. O(1) 真的代表「只执行一次」吗?它和「常数级」的准确含义是什么?
  3. 均摊复杂度用在什么场景?和「平均复杂度」的区别在哪?

2. 模块二:线性结构(第 5–10 讲)

讲次核心知识点课程原案例
05 数组随机访问 O(1);数组从 0 编号是为了寻址少一次减法a[k] 地址 = base + k×type_size(若从 1 开始则多减一次)
06 链表(上)单向/双向/循环链表;用链表实现 LRU 缓存淘汰LRU:新访问的放头部,满时淘汰尾部
07 链表(下)写对链表代码的 6 个技巧理解指针含义、警惕丢失指针、利用哨兵节点简化
08 栈后进先出;浏览器前进/后退的双栈实现后退栈 + 前进栈,前进后退就是两个栈互相倒数据
09 队列先进先出;线程池等有限资源池用队列有界队列处理「生产者快、消费者慢」的缓冲
10 递归递归三要素(终止条件/递推公式/返回值);警惕堆栈溢出三行代码找「最终推荐人」(递归查上级,注意环导致死循环)

引发思考:

  1. 为什么数组查询快、插入慢,链表正相反?根本原因是「连续存储 vs 链式存储」?
  2. 浏览器前进后退,为什么单栈做不了、必须双栈?
  3. 递归的「堆栈溢出」在阶段一《内存知识》里对应哪块内存?怎么用「尾递归/迭代」规避?

3. 模块三:排序与查找(第 11–16 讲)

讲次核心知识点课程原案例
11 排序(上)冒泡/插入/选择;插入比冒泡更受欢迎(交换次数少)三种 O(n²) 排序的稳定性与移动次数对比
12 排序(下)归并 O(nlogn) 稳定、快排 O(nlogn) 不稳定;快排思想 O(n) 找第 K 大分治 + 分区,一遍 partition 定位第 K 大
13 线性排序桶排序/计数排序/基数排序 O(n);按年龄给 100 万用户排序年龄范围小 → 计数排序,O(n) 秒排
14 排序优化通用排序函数怎么实现(业界:快排 + 小数据插排 + 三数取中)C 的 qsort、Java 的排序是怎么组合算法的
15 二分查找(上)二分 O(logn);最省内存的查找(只依赖数组下标)递归/非递归二分,警惕三个易错点
16 二分查找(下)二分变体;快速定位 IP 对应省份查「最后一个小于等于目标值」的变体二分

引发思考:

  1. 为什么插入排序比冒泡排序「更受欢迎」?(同 O(n²),但移动/交换成本更低)
  2. 线性排序(计数/桶/基数)为什么能突破 O(nlogn) 下限?它牺牲了什么?(数据范围)
  3. 二分查找的三个经典 bug 是什么?(循环条件、mid 取值、low/high 更新)——手写一遍看看会不会错。

4. 模块四:跳表 + 散列表 + 哈希(第 17–22 讲)

讲次核心知识点课程原案例
17 跳表链表加索引实现 O(logn);Redis 有序集合为什么用跳表不用红黑树跳表实现简单、支持按区间查(zrange)
18 散列表(上)散列函数、哈希冲突(开放寻址/链表法);Word 拼写检查散列表 = 数组 + 散列函数,O(1) 查单词
19 散列表(中)打造工业级散列表:装载因子、动态扩容、高效散列函数装载因子过大触发扩容,扩容时数据搬迁
20 散列表(下)散列表 + 链表 = LRU / LinkedHashMapJava LinkedHashMap 用双向链表维护插入/访问顺序
21 哈希算法(上)哈希算法四大要求;防止用户信息脱库(加盐哈希)密码不能明文/简单哈希存,要加盐 + 慢哈希
22 哈希算法(下)哈希在分布式系统中的应用负载均衡、分片、一致性哈希、分布式存储

引发思考:

  1. Redis 的 Sorted Set 底层为什么是「跳表 + 字典」组合?只用一个行不行?
  2. 哈希冲突的「开放寻址」和「链表法」各自适合什么场景?(数据量、缓存友好性)
  3. 为什么说「加盐哈希」能对抗彩虹表攻击?盐应该存哪?
  4. 一致性哈希为什么能解决「加机器导致缓存大量失效」?(和阶段七分布式联动)

5. 模块五:树(第 23–29 讲)

讲次核心知识点课程原案例
23 二叉树(上)完全二叉树、什么样的树适合数组存储完全二叉树用数组存(下标 i 的孩子是 2i、2i+1)
24 二叉树(下)二叉查找树;有了散列表为什么还要树散列表无序、扩容慢,树支持有序遍历和范围查
25 红黑树(上)工程中都爱用红黑树:近似平衡、增删改查稳定 O(logn)平衡二叉树 vs 红黑树的取舍
26 红黑树(下)红黑树的左旋/右旋、变色;实现技巧「实现红黑树的几个诀窍」
27 递归树用递归树求递归复杂度归并、快排的递归树画法,替代主定理
28 堆堆的插入/删除;堆排序为什么没快排快堆排序访问不连续(缓存不友好)
29 堆的应用Top10 热门搜索词(小顶堆)维护一个 10 元素小顶堆,O(nlog10)

引发思考:

  1. 「完全二叉树用数组存」和「堆用数组存」是同一件事吗?下标父子关系是什么?
  2. 红黑树、AVL、跳表,各自「牺牲了什么换来了什么」?
  3. 堆排序不如快排快,为什么?「缓存友好性」在阶段一《内存知识》里对应什么概念?(局部性原理)

6. 模块六:图(第 30–31 讲)

讲次核心知识点课程原案例
30 图的表示邻接矩阵 vs 邻接表;微博/微信好友关系怎么存社交网络稀疏图用邻接表(或反向邻接表存粉丝)
31 搜索BFS / DFS;三度好友关系从你出发 BFS 三层,找出三度好友

引发思考:

  1. 微博(大 V 粉丝千万)和微信(双向好友),图的存储结构怎么选?
  2. BFS 为什么用队列、DFS 为什么用栈(或递归)?「最短路径」为什么必须 BFS?

7. 模块七:字符串匹配(第 32–36 讲)

讲次核心知识点课程原案例
32 字符串(上)用哈希做高效字符串匹配(RK 算法)先比对哈希值,相同再逐字符确认
33 字符串(中)文本编辑器查找功能(BM 算法:坏字符 + 好后缀)从右往左匹配,坏字符规则快速后移
34 字符串(下)KMP 算法(好前缀规则)BM 理解后,KMP 的 next 数组就通了
35 Trie 树搜索引擎关键词提示(前缀树)输入「你」提示「你好」「你在干什么」
36 AC 自动机多模式串匹配 → 敏感词过滤Trie + KMP 的失败指针,一次扫描匹配多个模式

引发思考:

  1. BM 和 KMP 的核心思想差在哪?(坏字符 vs 好前缀,谁更适合实际工程)
  2. Trie 树解决什么问题?它和散列表比,在「前缀匹配」上强在哪?
  3. 敏感词过滤为什么要用 AC 自动机,而不是把每个词都跑一遍 KMP?

8. 模块八:高级算法思想(第 37–42 讲)

讲次核心知识点课程原案例
37 贪心贪心算法 + 霍夫曼编码Huffman 压缩编码(频率高的用短码)
38 分治分治思想MapReduce 的大规模计算(分而治之)
39 回溯回溯 = 深度优先 + 撤销选择电影《蝴蝶效应》类比;八皇后、0-1 背包
40 初识 DP动态规划入门双十一购物凑单(满减最优组合)
41 DP 理论最优子结构、无后效性、重复子问题三个特性是「能不能用 DP」的判据
42 DP 实战动态规划实现搜索引擎拼写纠错(编辑距离)

引发思考:

  1. 贪心、回溯、分治、动态规划,四个思想各自的「适用场景」和「能否得最优解」?
  2. 「最优子结构 + 无后效性」为什么是 DP 的敲门砖?举一个不满足的例子。
  3. 双十一凑单,为什么不能用贪心(每次选最大可用券),而要用 DP?

9. 模块九:综合应用(第 43–51 讲)

讲次核心知识点课程原案例
43 拓扑排序有向无环图的依赖排序确定代码源文件的编译依赖顺序
44 最短路径Dijkstra 算法地图软件算最优出行路径
45 位图位图 + 布隆过滤器网页爬虫 URL 去重(亿级 URL 内存爆炸)
46 概率统计朴素贝叶斯垃圾短信过滤(概率分类)
47 向量空间向量相似度简单音乐推荐系统
48 B+ 树MySQL 索引底层 = B+ 树从「查询 + 区间查询」需求一步步推导出 B+ 树
49 A* 搜索启发式搜索游戏中的寻路(估价值引导)
50 索引海量数据索引设计索引结构选型(跳表/B+树/倒排)
51 并行算法并行分治用并行提高算法执行效率

引发思考:

  1. 第 48 讲是「金讲」:为什么 MySQL 索引用 B+ 树,而不是散列表、二叉树、跳表?(从「范围查询 + 磁盘 IO 次数 + 稳定」三个角度,还原课程里的推导过程)
  2. 布隆过滤器为什么能「用一点点内存判重」,代价是什么?(误判率)——和阶段四 Redis 联动。
  3. 地图导航用 Dijkstra,游戏寻路用 A*,两者差在哪?(启发函数)

10. 模块十:算法实战(第 52–56 讲,全课升华)

这 5 讲是「把前面学的知识,用来拆解真实系统的底层」——也是这门课的真正价值所在。

讲次拆解的系统用到哪些数据结构
52 实战(一)Redis 常用数据类型String→SDS、Hash→哈希表、List→双向链表/压缩列表、ZSet→跳表
53 实战(二)搜索引擎倒排索引、Trie、跳表、B+ 树、AC 自动机
54 实战(三)高性能队列 Disruptor环形数组(RingBuffer)、无锁并发
55 实战(四)微服务鉴权 + 限流位图/布隆过滤器(token)、令牌桶/滑动窗口(限流)
56 实战(五)短网址系统哈希算法(进制转换)、散列表(存储映射)

引发思考:

  1. 学完这 5 讲,你能不能用一句话回答:「Redis 快、搜索引擎快、Disruptor 快,背后的数据结构分别是哪几个?」
  2. 短网址系统的核心是什么?(把长 URL 映射成短码 = 哈希 + 进制转换,再查表还原)
  3. 学完整门课,回头再看阶段四《Redis》和《Elasticsearch》,你是不是能「看到」它们底层的数据结构了?

11. 学完这门课,你要能回答的 5 个终极问题

  1. 什么是复杂度分析?为什么它是「算法学习的精髓」?
  2. 从数组到 B+ 树,画出这些数据结构的「增删改查复杂度对比表」。
  3. Redis 的 Sorted Set、MySQL 的索引、搜索引擎的倒排索引,底层各用了什么结构?为什么?
  4. 贪心、分治、回溯、动态规划,四个思想的核心区别和适用边界。
  5. 给定一个业务需求(如「实现一个排行榜」「实现一个短网址」),你能独立选型数据结构并说明理由吗?

阅读顺序提示:这门课是阶段三的「第一课 + 主线」,建议用 2~3 个月精读,配合手写实现(数组、链表、栈、队列、树、图、快排、二分)和刷题(第 62–68 讲「春节 7 天练」就是配套练习)。

—— 这是「细化版」学习指南的样板格式。其余课程可按同样深度逐一生成。