《Hello 算法》导读:算法无处不在——从查字典、理牌到找零,理解二分查找、插入排序与贪心算法
谈到"算法",很多人第一反应是复杂的数学公式。但实际上,大量算法的核心并不依赖高深数学,而是建立在简单的基础逻辑之上,它们就藏在日常生活的各种操作中。本文基于《Hello 算法》英文版开篇章节 en/docs/chapter_introduction/algorithms_are_everywhere.md,通过"查字典""整理扑克牌""超市找零"三个再熟悉不过的生活场景,带你零基础认识二分查找、插入排序与贪心算法三大经典主题,并结合仓库内真实的代码实现与专题文档,讲清它们背后的数据结构与算法本质。读完本文,你不仅能准确说出这些算法的原理、适用场景与复杂度特征,还能在仓库中找到对应的一键可运行源码,为后续系统学习打好"生活化"的认知基础。
一个反直觉的事实:你早就"会"算法了
在正式学习算法之前,章节首先抛出一个有趣的观点:很多人在不知不觉中已经学会并使用了不少算法,只是没有用术语称呼它们。
这一观点揭示了学习数据结构和算法的正确姿态——不要把这些概念当成陌生的、抽象的数学对象,而应从可感知的日常行为出发。文档指出,查字典这种小学生必备技能,本质就是著名的"二分查找"算法;而只要理解了"有序数组 + 逐步缩小范围"的关系,就同时建立起了数据结构(字典 ≈ 有序数组)与算法(查找过程 ≈ 二分查找)之间的桥梁。这正是《Hello 算法》全书反复强调的"从生活切入、从代码印证"的学习路径。
场景一:查字典 = 二分查找(Binary Search)
假设在英文词典中查找一个以字母 开头的单词,我们通常不会从第一页逐页翻找,而是这样做:
- 把词典翻开到大约一半的位置,查看该页第一个单词,假设它以字母 开头;
- 因为 在字母表中排在 之后,所以可以直接忽略前半本,把搜索范围缩小到后半本;
- 重复执行第 1、2 步,直到翻到以 开头的单词所在的那一页。
这个过程正是对"搜索区间减半"思想的反复应用:每次比较中间位置,就能排除掉一半不可能包含目标的数据。从数据结构角度看,词典可视为一个已按字母排序的"数组";从算法角度看,这套查词动作就是著名的二分查找。
源码印证。 仓库 en/codes/c/chapter_searching/binary_search.c 给出了两种区间写法的完整实现:
/* Binary search (closed interval on both sides) */
int binarySearch(int *nums, int len, int target) {
int i = 0, j = len - 1;
while (i <= j) {
int m = i + (j - i) / 2; // 计算中点下标 m
if (nums[m] < target) // 目标在区间 [m+1, j]
i = m + 1;
else if (nums[m] > target) // 目标在区间 [i, m-1]
j = m - 1;
else
return m; // 找到目标,返回下标
}
return -1; // 未找到,返回 -1
}
文件还给出了另一种"左闭右开区间"写法 binarySearchLCRO,循环退出条件变为 i < j、收缩区间时执行 j = m。两种写法对应教材中经典的闭区间与左闭右开区间约定,可对照阅读(参见 binary_search.c)。该文件对应的专题文档 en/docs/chapter_searching/binary_search.md 会进一步推导其时间复杂度与适用前提(数据有序、支持随机访问)。理解这个例子后你会发现,二分查找并不神秘——它只是把人类查词典的本能动作形式化了。
场景二:整理扑克牌 = 插入排序(Insertion Sort)
打牌时把手中的牌按从小到大排列,通常的做法是:
- 把手中的牌划分为"有序区"与"无序区",初始时假设最左侧一张牌已经有序;
- 从无序区取出一张牌,插入到有序区中的正确位置;插入后,最左侧两张牌即处于有序状态;
- 重复执行第 2 步,直到所有牌都排好序。
这就是"插入排序"的直观形态。文档特别指出,插入排序对规模较小的数据集非常高效,许多编程语言的内置排序实现内部就使用了插入排序。
源码印证。 在 en/codes/c/chapter_sorting/insertion_sort.c 中,可以看到与理牌动作一一对应的实现:
void insertionSort(int nums[], int size) {
for (int i = 1; i < size; i++) {
int base = nums[i], j = i - 1;
// 将 base 插入到已排序区间 [0, i-1] 的正确位置
while (j >= 0 && nums[j] > base) {
nums[j + 1] = nums[j]; // 将元素右移腾出位置
j--;
}
nums[j + 1] = base; // 落位
}
}
外层循环维护"已排序前缀 [0, i-1]",内层循环不断将更大的元素右移、为待插入元素 base 腾出空位——这正对应现实中"把某张牌抽出来,依次挪动前面的牌,再插回去"的整套动作。更完整的复杂度分析与优化讨论见 en/docs/chapter_sorting/insertion_sort.md。
场景三:超市找零 = 贪心算法(Greedy Algorithm)
假设在超市消费了 元,付给收银员 元,则需要找回 元。收银员会这样操作:
- 现有小于 的可用面额为 、、、;
- 先取出其中最大的 ,剩余应找 ;
- 再从剩余可选面额中取出最大的 ,剩余 ;
- 取出最大的 ,剩余 ;
- 找零完成,解为 。
上述每一步都选择"当前看起来最优"的面额(取不大于剩余金额的最大者),这就是数据结构与算法中的贪心算法。
源码印证与一个重要提醒。 仓库 en/codes/c/chapter_greedy/coin_change_greedy.c 给出了这一贪心策略的实现,其主程序同时演示了边界情况:当硬币面额为 {1, 5, 10, 20, 50, 100} 这类"彼此成倍数"的组合时,贪心可以保证得到全局最优解(例如找 元的最小硬币数);但当面额组合不合理(如 {1, 20, 50} 找 元,或 {1, 49, 50} 找 元)时,贪心反而给出较差的解——真正的局部最优不等于全局最优。这也解释了为什么贪心策略需要证明可行性,以及后续章节会引入动态规划等更普适的方法来求解此类问题。相关理论背景见 en/docs/chapter_greedy/greedy_algorithm.md。
从生活到计算机:为什么要抽象"算法"?
从做饭到星际旅行,几乎所有问题的求解都蕴含着算法。而计算机的出现,让我们能够把数据结构存入内存,并编写代码驱动 CPU 与 GPU 去执行算法,从而把现实问题搬到计算机中,以更高效的方式解决各种复杂问题。这正是《Hello 算法》开篇要传达的认知闭环:
- 数据结构回答"数据怎么组织"(如有序数组、链表、哈希表);
- 算法回答"问题怎么求解"(如二分查找、排序、贪心策略);
- 代码则把两者落地为可运行、可验证的步骤。
本书的每一章都延续这种"生活实例 → 图示推演 → 多语言代码"的写作范式。上文涉及的三个算法,仓库分别在 二分查找专题、排序专题 与 贪心专题 中展开;所有示例代码均可在 en/codes 目录下按语言(C、C++、Java、Python、Go、Rust、Swift、TypeScript、JavaScript 等)找到,例如 en/codes/python/chapter_searching/、en/codes/java/chapter_sorting/、en/codes/cpp/chapter_greedy/ 等,且多数直接附带可运行的 main 入口。
如果数据结构、算法、数组、二分查找等概念对你而言还只有模糊印象,不必担心——正如开篇所说,你早已在生活中熟练运用它们,接下来要做的,只是顺着这条从"生活常识"到"精确术语"的线索,系统进入数据结构和算法的世界。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00


