phase 5 part 5: cs algorithms, network-os, web-security topics with tested examples; all 43 stacks pass --strict

This commit is contained in:
Shikui Wang committed 2026-10-23 16:47:11 +08:00
1 parent f695bbd7cc
commit 691f738f5f
22 files changed
+1955 -37

No files matched your search

@@ -0,0 +1,73 @@
---
id: cs.algorithms.scenario.business-algorithms
title: 业务中的算法:热门问题 Top K、任务依赖排序、相似问题去重和缓存淘汰
type: scenario
domain: cs
stack: [algorithms, redis, langgraph]
tags: [Top K, 拓扑排序, 编辑距离, LRU, 去重, 复杂度]
level: intermediate
prerequisites: [cs.algorithms.complexity-patterns]
est_hours: 1.5
related: [cs.algorithms.interview]
week: [16]
---
# 业务中的算法:热门问题 Top K、任务依赖排序、相似问题去重和缓存淘汰
## 业务背景与问题
AI 客服运营后台需要:
1. 每小时展示用户最常问的 20 个问题(每小时几十万条消息);
2. 知识库导入任务有依赖(先解析、再分块、再嵌入、再建索引),要按正确顺序执行,并发现配置中的循环依赖;
3. 标注 Bad Case 时,大量问题只是错别字或说法略有不同,需要聚合去重;
4. 进程内缓存最近查询的文档,内存有限。
## 约束
- 统计要在秒级完成。
- 去重不能误合并意思不同的问题。
## 方案设计
1. **Top K**:先对问题文本做规范化(去空白、统一全半角),用哈希表计数,再用大小为 K 的堆取前 K,O(n log K);多实例时用 Redis 有序集合 `ZINCRBY` + `ZREVRANGE` 汇总。
2. **任务依赖**:用拓扑排序得到执行顺序,检测到环时拒绝保存配置;同层没有依赖关系的任务可以并行。
3. **相似去重**:先按规范化文本精确去重;再对候选对计算编辑距离(短文本)或向量相似度(语义),超过阈值的合并为一组,人工确认后生效。编辑距离是 O(mn),只对长度相近的候选对计算,避免 O(n²) 两两比较全部。
4. **缓存**:LRU 淘汰;Python 中可直接用 `functools.lru_cache` 或 `OrderedDict` 实现。
## 关键代码
```python
from patterns import edit_distance, top_k_frequent, topo_order
hot = top_k_frequent((normalize(m.text) for m in messages), 20)
order = topo_order({"index": ["embed"], "embed": ["chunk"], "chunk": ["parse"]})
if order is None:
raise ValueError("任务配置存在循环依赖")
def similar(a: str, b: str) -> bool:
if abs(len(a) - len(b)) > 2: # 先用长度剪枝
return False
return edit_distance(a, b) <= max(1, len(a) // 10)
```
完整实现和测试:[examples/patterns](../examples/patterns/)。
## 取舍
| 选择 | 优点 | 缺点 |
| --- | --- | --- |
| **精确计数 + 堆(本方案)** | 结果准确 | 内存随不同问题数增长 |
| 近似算法(Count-Min Sketch 等) | 内存固定 | 有误差 |
| 编辑距离去重 | 适合错别字 | 识别不了同义改写,需要配合向量相似度 |
## 易错点
- 没有规范化就计数,同一问题被拆成多个。
- 对全部问题两两计算相似度,O(n²) 跑不完。
- 去重阈值过松,把“退货”和“退款”合并(它们的编辑距离只有 1,但业务含义不同)——相似度只是候选,需要人工确认或结合业务规则。
## 面试怎么讲
> “运营后台的热门问题,我先做文本规范化,用哈希表计数加大小为 K 的堆取 Top K,复杂度 O(n log K),多实例用 Redis 有序集合汇总。导入任务的依赖用拓扑排序确定顺序并检测环。Bad Case 去重先精确去重,再按长度剪枝后算编辑距离,阈值只产生候选,避免把‘退货’和‘退款’这种只差一个字但意思不同的问题合并。”