字典树(Trie):用共享前缀把字符串检索从O(n)降到O(L)

假设你在搜索引擎输入框里键入"goog",下拉列表立刻弹出"google"、“google maps”、“google translate"等一系列建议。这些结果是怎么在毫秒级时间内出现的?如果用哈希表存储所有可能的搜索词,每次按键都需要遍历整个哈希表来找出以当前输入为前缀的词——当词库达到百万级别时,这种做法显然不可行。 ...

12 min · 5578 words

并查集:从社交网络连通性到LeetCode通关的完整指南

假设你正在开发一个社交网络应用,需要实时回答"用户A和用户B是否在同一个社交圈内"这类查询——用户之间可以通过好友关系不断形成更大的圈子。每添加一个好友关系,圈子就可能合并;每查询一次,就需要判断两个用户是否已经连通。如果用传统的图遍历方法,每次查询都可能需要遍历整个图,当用户量达到百万级别时,系统会变得极其缓慢。 ...

10 min · 4550 words

堆与优先队列为什么能在对数时间内找到第K大元素:从完全二叉树到堆排序的完整技术解析

1964年,J.W.J. Williams在发表堆排序算法时,顺带发明了一种被称为"堆"的数据结构。他可能没想到,这个最初为排序服务的数据结构,会在六十年后成为每一位程序员面试的必考内容。从操作系统进程调度到网络路由的最短路径计算,从数据库查询优化到实时数据流的中位数统计,堆的身影无处不在。 ...

10 min · 4559 words

深度优先与广度优先搜索:从栈与队列的选择到最短路径的博弈

给定一个迷宫,从入口到出口有多条路径。你应该选择哪种策略?一种方式是沿着每条路一直走到底,走不通就返回上一个分叉口换条路——这就是深度优先搜索。另一种方式是先探索所有离入口距离为1的格子,再探索距离为2的格子,层层推进——这就是广度优先搜索。 ...

9 min · 4491 words

贪心算法:为什么每次只做局部最优选择却能得到全局最优解

给定一组活动,每个活动都有开始时间和结束时间,要求选出最多的互不重叠的活动。最直观的思路是尝试所有可能的组合,但这样的时间复杂度是指数级的。如果换一个角度:每次都选择结束时间最早且不与已选活动重叠的活动,只需要一次遍历就能得到最优解。 ...

11 min · 5441 words

单调栈算法:如何用O(n)时间找到下一个更大元素

给定一个长度为100万的数组,要求找出每个元素右侧第一个比它大的元素。最直观的做法是:对每个元素,向右扫描直到找到更大的元素。最坏情况下,每个元素都需要扫描到数组末尾——总的时间复杂度是$O(n^2)$。 ...

11 min · 5232 words

回溯算法:从决策树到剪枝优化的完整LeetCode通关指南

假设你需要生成数组 [1, 2, 3] 的所有排列。最直观的想法是写三重循环,每一层选择一个不同的元素——但如果数组长度是 10 呢?你需要写 10 层嵌套循环。更糟糕的是,如果数组长度不固定呢? ...

12 min · 5987 words