我自己刚学算法那会儿,干过一件特别丢人的事:把网上几道热门题的题解背了下来,以为能应付面试,结果面试官把题目改了一个条件,我当场就卡住了。后来带过不少刚起步的同事,也回答过很多“算法小白”的问题,发现大家问得最多的其实不是“这道题怎么解”,而是“为什么我看了半天题解还是不会做”“明明照着写了,一跑就超时”“这个算法到底什么时候该用”。这些问题的根源,往往不是天赋不够,也不是刷题量不达标,而是对算法的理解方式,从一开始就跑偏了。
这篇文章我想从新手最常见的困惑出发,把“简单算法”这个概念拆开揉碎讲清楚。排序、查找、递归、复杂度分析都会聊到,也会把实际调试过程中踩过的坑一并列出来。内容不追求面面俱到,但保证每一个点都能直接落地,适合正在学数据结构与算法、准备笔试面试,或者工作中突然发现自己欠了一屁股“基础债”的朋友。
1. 新手学算法的几个典型误区
1.1 背代码而不是理解思路
我见过太多人拿着冒泡排序的代码,能一字不差默写出来,但问他“内层循环为什么是 n - i - 1,而不是 n - i”,就答不上来了。这就是典型的“会背不会用”。面试官或者实际项目里,几乎不会有题目让你“原样默写某个算法”,他们更关心的是:你能不能根据具体的输入、需求、数据规模和约束条件,从你的知识库里挑出合适的算法,然后改造成能解决当前问题的代码。
那怎么避免背代码呢?我的办法比较笨,但特别有效:每学完一个算法,不看参考代码,自己拿一个具体的小数组,比如 [5, 1, 4, 2, 8],在纸上把每一轮结束后的数组状态画出来。先把过程走明白,再谈代码实现。甚至可以在代码里临时加一个打印语句,把每次交换后的数组打出来,亲眼看着数据一点点“动起来”。这一步的反馈非常直接,比你盯着代码看十遍都有用。
1.2 只刷题不看复杂度
“不管三七二十一,先暴力解出来再说”——这是新手的通病。暴力解法本身没什么问题,很多题目暴力解能过,是因为数据范围小。但你要是拿同样的思路去处理真实项目里的百万级、千万级数据,程序估计要跑到天荒地老。
我举个例子。给你一个长度为 n 的数组,要判断里面有没有重复元素。最简单粗暴的方式是两层循环,时间复杂度是 O(n²)。当 n=10 时,这点计算量无所谓;但当 n=10^6 时,就意味着大约 10^12 次基本操作,现代 CPU 每秒能执行的操作量级大概是 10^9 次左右,你自己算算要跑多久。而用哈希表(unordered_set)或者先排序再比较相邻元素,时间复杂度立刻降到 O(n) 或 O(n log n),可能只需要几毫秒。
所以,每写完一段代码,养成一个习惯:看一眼输入规模,估算一下自己的解法在最坏情况下会跑多少次循环、开多大内存。这比你会了多少个冷门算法重要得多。
1.3 忽视边界条件和输入输出细节
很多算法代码核心逻辑写得没问题,但一提交就“答案错误”或者“运行时错误”,问题通常出在边界条件上:数组为空、只有一个元素、元素全是负数、输入里混着重复值、整型溢出……这些情况虽然看起来“极端”,但实际工程和面试题里反而最常见。
我常用的一个笨办法是:写完代码之后,先别急着提交,自己构造几组边界用例。比如排序算法就测一测空数组、只有一个元素、已经有序的数组、完全逆序的数组、全部元素相等的数组。如果这些极端情况都能跑通,代码的可靠性会高很多。注意,测试不是“做样子”,你要真的把代码跑起来看结果,而不是在脑子里过一遍就觉得没问题。脑内模拟往往会有盲区。
1.4 盲目追求高深算法,忽略基础
网上看到“3DCNN和C3D算法对比”“粒子群算法原理”“SVPWM算法详解”,觉得高级,转头就去啃,结果被公式劝退,连带着基础也没学好。这个心态我特别理解,谁不想一步到位呢?但这里我想说一句可能不太中听的话:算法学习是有顺序的。
像 3D 卷积、粒子群、SVPWM、FOC 这些,有它们各自的应用场景,比如视频理解、优化问题、电机控制。但它们的底层,都建立在数组、链表、树、图、排序、查找、递归、概率统计这些基础上。你现在连二叉树的遍历都没搞明白,就去看多模态融合、强化学习、深度学习的文章,除了增加焦虑,不会带来任何真正的提升。我的建议是:先把基础算法的地基打好,再去接触领域算法。地基不牢,楼盖得越高越危险。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 先把地基打好:时间复杂度和空间复杂度
2.1 时间复杂度:先从“数循环次数”开始
时间复杂度这个概念,大学课本里喜欢用渐近记号来定义,但新手初学没必要太纠结数学推导。你只要抓住一点:把算法执行的基本操作次数,表达成关于输入规模 n 的函数,然后保留增长最快的项,去掉系数和低阶项,就是时间复杂度。
比如一段两层循环,外层跑 n 次,内层也跑 n 次,那么基本操作次数大约是 n * n = n²,复杂度就是 O(n²)。如果你只有一个循环,那就是 O(n)。如果你不管输入多大,都只做一次操作,那就是 O(1)。
这里有一个很多新手会混淆的点:时间复杂度描述的是“增长趋势”,不是“精确运行时间”。一个 O(n) 的算法在数据量小时,可能跑
