我第一份工作入职第一周,导师让我写一个冒泡排序。我当时觉得这还不简单,两分钟交上去,结果他看了一眼就问:“这个排序稳定吗?最好情况和最坏情况时间复杂度差多少?能不能优化?”我当场愣住。后来我才发现,算法这行真正难的从来不是“写出来”,而是“想明白”。很多新手容易栽跟头,不是因为代码量不够,而是对最基础的概念、最常见的坑没有建立起系统的认知。
这篇文章就是写给正在学算法的新手朋友。我会结合实际场景,把复杂度、排序、二分查找、递归、动态规划这些绕不开的简单算法拆开讲清楚,同时把新手最容易踩的坑和排查思路一并整理出来。不管你是科班在读还是转行自学,只要能把这篇内容吃透,再回头刷题或做项目,会觉得顺很多。整篇内容我已经过滤掉了晦涩的数学推导,尽可能用实际案例和代码说话,你可以直接照着拿到自己的代码里跑一遍。
1. 算法学习,先搞懂这5个底层概念
很多人一上来就刷 LeetCode,觉得“题刷得越多越厉害”。我不反对刷题,但你得先搞懂几个底层概念,否则刷题只是在背答案,换个场景就不会了。我个人认为,新手阶段最值得先花时间的是下面这5个点:时间复杂度、数据结构选型、递归思想、空间换时间、调试意识。
1.1 时间复杂度:不要把 O(n) 和“运行时长”划等号
时间复杂度,准确说是“渐近时间复杂度”,它描述的是算法执行时间随数据规模增长的变化趋势,而不是具体跑多少毫秒。举个实际例子,你的机器跑一个 O(n) 的算法,在 n=1000 时可能只要0.01秒;但一个 O(n²) 的算法在 n=1000 时可能要1秒;看起来差距不大,可当 n 变成 100000 时,O(n) 还是很快,而 O(n²) 就会跑到天荒地老。
理解这个概念,你需要掌握几个常见复杂度量级,从快到慢大概是:O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(2ⁿ)。很多新手会忽略常数项,比如 O(2n) 和 O(100n) 本质上都是 O(n),但在实际使用中常数项也值得关注。面试或工程里,我们通常会关注最坏情况复杂度,同时也要留意平均情况,比如快速排序平均 O(n log n),但最坏 O(n²),这点后面细说。
1.2 数据结构:算法和容器是绑定的
学算法不能脱离数据结构。你要排序,得知道数组和链表哪个更适合随机访问;要频繁在头部插入删除,那链表比数组好使;要实现撤销操作,栈是天然选择;要实现排队场景,队列更合适;要快速判断一个元素是否存在,哈希表的时间复杂度是 O(1)。
我见过不少新手,链表还没搞明白就去啃图论,结果写出来的“图遍历”实际上是在数组里瞎转。我给的建议是:先把数组、链表、栈、队列、哈希表、树这六种基础结构的基本操作和适用场景吃透,再开始学排序和搜索。数据结构是容器的选型,算法的本质是在容器上做的操作策略,两者无法分开谈。
1.3 递归思想:先学会“相信函数”
递归是新手最头疼的点之一。我总结了一个方法:你要学会“相信这个函数能完成它的功能”。比如你要写一个计算阶乘的函数fact(n),你只需要明确两点:第一,n=0或n=1时返回1,这是递归出口;第二,对于任意n>1,fact(n) = n * fact(n-1),这里假设fact(n-1)已经能正确工作。
很多新手写递归时会不由自主地在脑子里展开全部调用链,试图“人肉模拟”每一层调用。这在递归深度很浅时还可以,一旦超过四五层就晕了。正确的做法是“宏观审视”,只关心当前这一层做什么、递归出口在哪里、参数如何向出口收敛。只要这三点想清楚,递归基本不会写错。当然,递归也并非没有代价,每一层调用都会产生函数栈帧,占用内存,深度太大还会栈溢出,这个我们后面详细展开。
1.4 空间换时间:算法的精髓之一
很多算法优化的核心思路就是“用空间换时间”。典型代表是哈希表和动态规划。哈希表用额外内存存储键值映射,换取 O(1) 的查询时间;动态规划用数组记录子问题的解,避免重复计算。新手在学算法时往往不舍得开数组,或者不知道怎么用缓存,导致写的代码逻辑对但性能差。
我建议你在分析任何算法的时候,都养成一个习惯:问自己“有没有什么东西被我重复算了很多次?能不能存下来复用?”这个问题一旦开始出现在你的脑子里,你对算法的理解就上了一个台阶。后文讲斐波那契数列时,你会看到同一个问题在“重复计算”和“记忆化”之间的巨大差异,那就是“空间换时间”最生动的演示。
1.5 调试与测试意识:新手最容易忽略的
很多新手写完代码能跑通就觉得自己“会了”,但算法题的坑往往藏在边界条件里。比如循环里数组越界、空数组、单元素数组、全相等数组、已经有序的数组……这些用例在实际工作中远比“标准样例”更容易暴露问题。我自己的习惯是:每次写完一个算法,先用最极端的几个例子测一下,再跑正常数据。不要嫌麻烦,这在找工作时就是你能不能通过面试的关键。
调试工具方面,IDE 的断点调试是必须掌握的,但很多人更喜欢用 print 大法,这也没问题。关键是要有“定位意识”:出问题时,不要满屏幕加 print,而是先根据报错信息判断是逻辑问题还是内存问题,再用二分法缩小排查范围。比如一个排序算法结果不对,就先打印中间状态,看第几次交换后顺序开始乱,这样很容易定位到具体的比较或交换逻辑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 新手必学的三大排序算法
排序算法是算法学习的“必修课”,也是面试常客。这部分只挑三个对新手最有价值的来讲:冒泡排序、选择排序、快速排序。归并排序也很重要,但它在理解了分治思想之后更容易上手,所以放到快速排序里一起说。
2.1 冒泡排序:理解“比较”和“交换”的入门砖
冒泡排序的思路很直白:从头到
