1.3 · 模式识别
目标: 发现两个问题共享结构时,让一个解法服务两者。
模式识别是什么
跨问题寻找共同结构,让一个算法 —— 也许带些小变体 —— 解决许多。
例子
模式 1 · 「找最大」
| 问题 | 变的是什么 |
|---|---|
| 找最高的学生 | 「高」 |
| 找最贵的产品 | 「贵」 |
| 找最长的河流 | 「长」 |
同一算法 —— max() —— 不同属性。
模式 2 · 「处理列表每项」
| 问题 | 每项动作 |
|---|---|
| 印每位学生姓名 | |
| 累加全部销售 | accumulate |
| 给每位家长发邮件 | send_email |
| 校验每条条目 | validate |
都是循环过一个集合,只变内部动作。
模式 3 · 「排序列表」
| 问题 | 排序键 |
|---|---|
| 按分数升序排学生 | score asc |
| 按重量降序 | weight desc |
| 按标题字母排书 | title |
同样排序算法;只比较函数变。
为何重要
- 把一种模式实现好后,未来类似任务几分钟搞定。
- 代码变通用 —— 接收列表和函数,对任何东西都能干。
- 库就是建立在公认模式上 (
map、filter、reduce)。
实例 · 机器人编程
两任务:
- 让机器人画正方形。
- 让机器人画等边三角形。
模式:「重复(前进、转角)」N 次。
text
对多边形每个角:
前进 side_length
转 exterior_angle1
2
3
2
3
只角度与角数不同。
python
def draw_polygon(sides, length):
for _ in range(sides):
move_forward(length)
turn(360 / sides)1
2
3
4
2
3
4
draw_polygon(4, 100) 画正方形;draw_polygon(3, 100) 画三角形;draw_polygon(8, 50) 画八边形。
值得知道的模式目录
| 模式 | 用途 |
|---|---|
| Iterate 迭代 | 走过列表 |
| Accumulate 累加 | 建累计 |
| Filter 筛选 | 保留满足条件的项 |
| Map 映射 | 变换每一项 |
| Search 搜索 | 找一项 |
| Sort 排序 | 给列表排序 |
| Group 分组 | 把项分类 |
| Aggregate 聚合 | 汇总一组 |
考试式题目
题(4 分): 两位学生发现他们写了类似代码:一个找最高同学,一个找列表中最贵的书。解释模式识别如何帮他们写可复用代码。
参考答案:
两题共享**「找最大项」模式:遍历列表、追踪迄今最好、最后返回。仅比较属性(高度 vs 价格)不同。学生可写通用函数**,接收列表与一个「键函数」描述要比较的属性,例如:
python
def find_max(items, key):
best = items[0]
for item in items[1:]:
if key(item) > key(best):
best = item
return best
find_max(students, key=lambda s: s.height)
find_max(books, key=lambda b: b.price)1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
这单一函数替代两个专门版、减少 bug、支援未来任何「找最大」任务。
关键要点
- 发现共同结构 → 写通用代码。
- 少数模式覆盖多数问题。
第 1 章总结
自测:能在 10 分钟内对小问题做完 IPO → 分解 → 模式 吗?能就前进。
➡️ 下一章:2 · 算法设计