--- id: cs.algorithms.complexity-patterns title: 复杂度分析和九个高频模式:哈希、滑动窗口、二分、堆、BFS、拓扑排序、动态规划、LRU、区间合并 type: lesson domain: cs stack: [algorithms] tags: [时间复杂度, 哈希表, 滑动窗口, 二分查找, 堆, Top K, BFS, DFS, 拓扑排序, 动态规划, LRU] level: basic prerequisites: [python.python.index] est_hours: 6 related: [cs.algorithms.scenario.business-algorithms, cs.algorithms.interview] week: [16] order: 1 --- # 复杂度分析和九个高频模式:哈希、滑动窗口、二分、堆、BFS、拓扑排序、动态规划、LRU、区间合并 > BOSS直聘 2026-10-23 的调研中有少数岗位明确提到算法 / 数据结构基础,笔试和一面中出现手写题的情况也不少。目标不是刷几百题,而是**掌握模式、能讲复杂度、写出无 bug 的中等题**。练习平台可用 LeetCode 中国站(力扣)。 ## 解释说明 ### 复杂度 | 复杂度 | 典型操作 | n = 10⁶ 时的感受 | | --- | --- | --- | | O(1) | 哈希表查找、数组下标 | 瞬间 | | O(log n) | 二分查找、堆操作 | 约 20 步 | | O(n) | 遍历 | 很快 | | O(n log n) | 排序 | 可以接受 | | O(n²) | 双重循环 | 太慢(10¹² 次) | 面试时先说暴力解及其复杂度,再优化,最后说明时间和空间复杂度。 ### 九个模式(何时想到它) | 模式 | 信号 | 例题 | | --- | --- | --- | | 哈希表 | “是否出现过”、“计数”、“配对” | 两数之和 | | 滑动窗口 | 连续子数组 / 子串 + 最长 / 最短 | 无重复字符的最长子串 | | 二分查找 | 有序、单调、“第一个满足条件的” | lower_bound、搜索旋转数组 | | 堆 | Top K、动态取最值、合并 K 个有序 | 前 K 个高频元素 | | BFS | 最短步数、层序遍历 | 网格最短路径 | | DFS / 拓扑排序 | 依赖关系、是否有环、所有方案 | 课程表 | | 动态规划 | 最优值 / 方案数、子问题重叠 | 编辑距离、爬楼梯、背包 | | 设计题 | 要求 O(1) 操作 | LRU 缓存 | | 排序 + 扫描 | 区间、会议室 | 合并区间 | ### 答题步骤 1. 复述题目,问清边界(空输入、重复、负数、数据规模); 2. 说思路和复杂度,得到认可后再写; 3. 写代码时变量命名清楚; 4. 用一两个例子手动走一遍,包括边界; 5. 说明可以改进的地方。 ## 案例 这些模式在业务中经常出现:热门问题统计(堆)、限流的滑动窗口、任务编排的依赖顺序(拓扑排序,LangGraph / CI 流水线都用到)、文本纠错与相似度(编辑距离)、缓存淘汰(LRU)、排班时间段合并(区间合并)。见[企业场景](scenarios/business-algorithms.md)。 ## 代码示例 [examples/patterns](examples/patterns/):9 个模式的实现 + 13 个测试(其中二分查找与标准库 `bisect` 随机对拍 200 次)。 滑动窗口: ```python def longest_unique_substring(s: str) -> int: last: dict[str, int] = {} left = best = 0 for right, ch in enumerate(s): if last.get(ch, -1) >= left: left = last[ch] + 1 last[ch] = right best = max(best, right - left + 1) return best ``` 二分查找(左闭右开,最不容易写错的模板): ```python def lower_bound(arr: list[int], target: int) -> int: lo, hi = 0, len(arr) while lo < hi: mid = (lo + hi) // 2 if arr[mid] < target: lo = mid + 1 else: hi = mid return lo ``` ## 易错点 - 二分查找的区间定义混乱(左闭右闭和左闭右开混用),导致死循环或越界。 - 滑动窗口中,重复字符在窗口左边界之外时也移动左边界(例如 "abba")。 - BFS 出队时才标记已访问,导致同一个节点多次入队。 - 递归 DFS 在深度很大时栈溢出(Python 默认递归深度约 1000)。 - 只写出代码不说复杂度。 ## 面试常问 - 手写:两数之和、最长无重复子串、二分查找、Top K、LRU、合并区间、课程表、编辑距离 / 爬楼梯。 - 哈希表的原理和冲突处理? - 快速排序的平均和最坏复杂度?