🔄 复习日 / Review Day 85
日期 / Date: 2026-07-08
回顾 / Covering: Days 81–84
📊 进度 / Progress
NeetCode: 68/150 · SysDesign: 60/40 · Behavioral: 60/40 · Frontend: 37/50 · AI: 30/30
🔥 2-day streak!
今天是复习日!回顾过去4天的内容。
Today is a review day! Let's revisit the last 4 days.
涵盖主题 / Topics covered:
- Day 81: Circuit Breaker · Last Stone Weight · Heap/Priority Queue pattern
- Day 82: Heap Deep Dive (K Closest Points + Find Median from Data Stream)
- Day 83: K Closest Points to Origin · Rate Limiting (Token Bucket, Sliding Window)
- Day 84: Task Scheduler · Dependency Injection (Without Frameworks)
📝 Quick Quiz — 3 Mini-Reviews
Q1: [💻 Algorithms — Heap Pattern]
你有任务列表 ['A','A','A','B','B','B'] 和冷却时间 n=2。Task Scheduler 的解法核心是什么?为什么需要一个 wait_queue(等待队列),而不是简单地从堆里反复取最大元素?
You have tasks ['A','A','A','B','B','B'] and cooldown n=2. What's the core insight of Task Scheduler? Why do we need a wait_queue alongside the heap?
<details><summary>显示答案 / Show Answer</summary>
贪心 + 冷却跟踪 / Greedy + Cooldown Tracking
核心洞察:每次优先执行剩余次数最多的任务,能最小化 idle 时间(贪心)。但同一任务两次执行之间必须间隔 ≥ n 个时间单位——这就是 wait_queue 的作用。
The key insight is greedy scheduling: always run the most-frequent available task to minimize idle time. But a task can't re-run for n time units after it executes. The wait_queue (a deque) tracks (available_at_time, neg_count) — when the current time matches a task's available_at_time, the task gets pushed back to the heap.
Without wait_queue, you'd re-schedule tasks too early and violate the cooldown constraint. The deque acts as a time-aware holding area: items enter in order and are released at the right moment.
面试要点: 堆解法 O(n log k),数学公式 O(n),面试时展示堆解法更能体现思维过程。
</details>
Q2: [🐍 Python Craft — Dependency Injection]
为什么说 Python 开发者"不需要 DI 框架,但需要 DI 思想"?给一个具体的例子说明没有 DI 时会遇到什么问题,以及如何用构造函数注入解决它。
Why do Python devs "not need a DI framework but need DI thinking"? Give a concrete example of what breaks without DI and how constructor injection fixes it.
<details><summary>显示答案 / Show Answer</summary>
可测试性 vs 隐式耦合 / Testability vs Implicit Coupling
没有 DI 时:类内部硬编码依赖(如 PostgresDB(host="prod"))。问题:
- 单元测试会真的连生产数据库
- 无法替换实现(换 MySQL?要改每个类)
- 依赖隐藏在构造函数内部,代码难以理解
With no DI, dependencies are hard-coded inside init. This means tests hit real databases, implementations can't be swapped, and dependencies are invisible from the outside.
构造函数注入解决方案:
# 依赖通过 __init__ 传入,不在内部创建
class UserService:
def __init__(self, db: Database, cache: Cache):
self.db = db # 外部注入
self.cache = cache
# 生产
svc = UserService(db=PostgresDB(), cache=RedisCache())
# 测试
svc = UserService(db=FakeDB(), cache=FakeCache()) # 无需改 UserService
三种无框架 DI 模式: 构造函数注入(最常用)、手写容器(中型项目)、函数式 DI(FastAPI 风格)。Python 的 Protocol 类让接口定义不需要继承,非常优雅。
</details>
Q3: [🏗️ System Design — Circuit Breaker]
断路器(Circuit Breaker)的三个状态是什么?在什么情况下它从"半开"状态转换回"开路"状态?它和简单的"重试 + 退避"有什么本质区别?
What are the 3 states of a Circuit Breaker? When does it transition from HALF-OPEN back to OPEN? What's the fundamental difference between Circuit Breaker and simple "retry with backoff"?
<details><summary>显示答案 / Show Answer</summary>
三态状态机 / Three-State FSM
| 状态 | 行为 | 转换条件 |
|---|---|---|
| CLOSED (正常) | 所有请求通过,记录失败次数 | 失败率超阈值 → OPEN |
| OPEN (断路) | 快速失败,不调用下游 | 等待冷却时间 → HALF-OPEN |
| HALF-OPEN (探测) | 放行少量请求测试下游 | 成功 → CLOSED;失败 → OPEN |
HALF-OPEN → OPEN: If the test request(s) fail while in HALF-OPEN state, the circuit immediately trips back to OPEN (resets the cooldown timer). This prevents hammering a still-recovering downstream service.
Circuit Breaker vs Retry+Backoff 的本质区别:
- Retry+Backoff: 假设"下游暂时有问题,多等一会儿可能好"——适合短暂抖动(网络抖动、单次超时)
- Circuit Breaker: 假设"下游可能持续故障,我要保护自己和下游"——适合系统性故障
Retry keeps hammering a dead service. Circuit Breaker fails fast during outages, protecting your own resources (threads, connections) and giving the downstream service time to recover without extra load. Use both together: Circuit Breaker wraps Retry (retry inside closed state only).
真实场景: Resilience4j (Java), Hystrix (deprecated), circuitbreaker in Python tenacity.
</details>
💡 复习巩固记忆,螺旋式上升。Review reinforces memory — each pass deepens understanding.
📅 明天继续新内容!New content resumes tomorrow!