Algorithms & Data Structures
"An algorithm must be seen to be believed." — Donald Knuth
掌握算法的关键在于识别模式,而非记忆答案。本综合指南涵盖了面试准备和实际后端工程中必不可少的数据结构与算法模式。
🎯 为什么这很重要
面试角度
- 80%+ 的编程面试题目集中在数组、字符串和数据结构上
- 公司期望你对核心算法(DFS、BFS、DP、二分查找)非常熟练
- 模式识别有助于通过类比已知模式来解决未见过的题目
后端工程角度
- 数据结构直接影响系统性能(HashMap 实现 O(1) 查找,B+ 树用于数据库索引)
- 算法驱动关键功能(搜索引擎使用字典树,路径规划使用 Dijkstra 算法)
- O(n²) 和 O(n log n) 之间的性能差异可能决定系统的可扩展性
实际影响:后端工程师选择错误的数据结构可能会使 API 响应时间从 10ms 退化到 1 秒——100 倍的性能下降,严重影响用户体验。
📚 学习路径
阶段一:基础(从这里开始)
这些是面试中出现频率最高的主题:
- 数组与字符串 - 内存布局、StringBuilder、二维数组
- HashMap 与 HashSet - 哈希函数、冲突解决、负载因子
- 树 - BST、遍历、LCA、序列化
- 双指针 - 对向指针、快慢指针
时间投入:2-3 周 | 面试频率:60%+
阶段二:核心模式
在基础上学习算法模式:
时间投入:2-3 周 | 面试频率:25%+
阶段三:进阶主题
攻克更复杂的数据结构:
时间投入:3-4 周 | 面试频率:15%+
阶段四:专项专题
专用数据结构:
- 字典树 - 前缀树、自动补全、字典应用
- 排序 - 归并排序、快速排序、TimSort、非比较排序
- 贪心算法 - 活动选择 、区间调度、哈夫曼编码
- 回溯 - 排列、组合、N 皇后
- 搜索策略 - 插值搜索、指数搜索、矩阵搜索
时间投入:2-3 周 | 面试频率:5%+
🏗️ 数据结构参考
复杂度一览
| 结构 | 访问 | 查找 | 插入 | 删除 | 使用场景 |
|---|---|---|---|---|---|
| Array | O(1) | O(n) | O(n) | O(n) | 随机访问,小型数据集 |
| ArrayList | O(1) | O(n) | O(1)* | O(n) | 动态数组,频繁访问 |
| LinkedList | O(n) | O(n) | O(1) | O(1) | 频繁插入/删除 |
| HashMap | - | O(1)* | O(1)* | O(1)* | 快速查找,缓存 |
| TreeMap | - | O(log n) | O(log n) | O(log n) | 有序迭代,范围查询 |
| HashSet | - | O(1)* | O(1)* | O(1)* | 去重,成员判断 |
| PriorityQueue | - | O(n) | O(log n) | O(log n) | 优先级任务,Top K |
| Trie | - | O(L) | O(L) | O(L) | 前缀搜索,自动补全 |
*平均情况;哈希函数不佳时最坏情况为 O(n)
Java 集合快速参考
// Lists
List<Integer> arrayList = new ArrayList<>(); // 快速访问
List<Integer> linkedList = new LinkedList<>(); // 快速插入/删除
// Sets
Set<Integer> hashSet = new HashSet<>(); // 快速,无序
Set<Integer> treeSet = new TreeSet<>(); // 有序,O(log n)
// Maps
Map<K, V> hashMap = new HashMap<>(); // 快速,无序
Map<K, V> treeMap = new TreeMap<>(); // 有序,O(log n)
Map<K, V> linkedMap = new LinkedHashMap<>(); // 插入顺序
// Deque
Deque<Integer> deque = new ArrayDeque<>(); // 快速,可调整大小
Queue<Integer> queue = new LinkedList<>(); // FIFO
Stack<Integer> stack = new Stack<>(); // LIFO(遗留类)
// Priority Queue
PriorityQueue<Integer> minHeap = new PriorityQueue<>(); // 最小值在顶部
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(
Collections.reverseOrder()); // 最大值在顶部
🧠 算法模式
模式识别指南
| 模式 | 使用时机 | 核心洞察 |
|---|---|---|
| 双指针 | 有序数组,配对求和,回文串 | 从两端向中间收缩 |
| 滑动窗口 | 带约束的子串/子数组 | 维护有效窗口 |
| 快慢指针 | 环检测,中间元素 | 以不同速度移动 |
| 合并区间 | 重叠区间 | 按起始时间排序 |
| 二分查找 | 有序数组,单调谓词 | 每次迭代排除一半 |
| 贪心 | 局部最优 → 全局最优 | 当下做出最优选择 |
| 回溯 | 所有组合/排列 | 探索所有可能,剪枝无效方案 |
| DP | 重叠子问题,最优子结构 | 缓存计算结果 |
| BFS | 最短路径(无权),层序遍历 | 基于队列的探索 |
| DFS | 路径查找,连通性 | 基于栈/递归的探索 |