一、算法概述:从菜鸟到老手的必修课
各位同学好,我是老张。今天咱们聊聊算法的基础概念。说实话,我教了这么多年C语言,发现很多同学一听到「算法」两个字就发怵。其实没必要,算法没那么玄乎。
先问大家一个问题:你平时写代码,是不是经常遇到「这个功能该怎么实现」的困惑?比如让你把一组数字从小到大排个序,或者从一堆数据里找出某个值。嗯,这些问题的解决方案,就是算法。
算法的本质:说白了,就是解决问题的步骤和方法。就像你做菜,先洗菜、再切菜、最后下锅炒——这就是一个算法。
1.1 算法的定义
算法(Algorithm)这个词,听起来高大上,其实老祖宗早就用了。中国古代的《九章算术》里就有很多算法。现代计算机科学里,算法的定义是:对特定问题求解步骤的一种描述。
我个人习惯把算法理解成「菜谱」。菜谱告诉你先放油、再放葱姜蒜、最后下主料——算法告诉计算机先做什么、再做什么、最后输出什么结果。
1.2 算法的五大特性
一个合格的算法,必须满足五个条件。我在项目中吃过不少亏,有些就是算法设计不严谨导致的。咱们一个一个说:
- 有穷性——算法必须在有限步骤内结束。不能死循环,不能无限跑下去。我曾经见过一个排序算法,数据量一大就卡死,后来发现是递归没写终止条件。
- 确定性——每一步操作都必须明确,不能有歧义。比如「把数字变大点」这种描述就不行,到底变大多少?要写清楚。
- 可行性——算法中的每一步都必须能通过有限次基本运算实现。你不能写「直接算出宇宙的终极答案」,这做不到。
- 输入——算法可以有零个或多个输入。比如求1到100的和,就不需要外部输入。
- 输出——算法至少有一个输出。没有输出的算法,就像做了饭不给人吃,毫无意义。
小提示:写算法时,先检查这五个条件。尤其是「有穷性」,很多bug都出在这里。
1.3 算法复杂度:为什么有的程序跑得慢?
好,现在你写出了一个能解决问题的算法。但问题来了:它快不快?占不占内存?
我记得刚工作那会儿,写了个数据处理的程序,功能完全正确,但一跑就是半小时。领导过来看了一眼,说:「你这算法复杂度太高了,换一种吧。」当时我一脸懵,后来才明白——算法复杂度就是衡量算法好坏的标准。
1.3.1 时间复杂度
时间复杂度,说白了就是算法运行需要的时间。但注意,不是精确的秒数,而是随着数据量增大,时间增长的趋势。
举个例子:你写个循环,从1加到n,时间复杂度就是O(n)。如果写个嵌套循环,那就是O(n²)。数据量一大,O(n²)比O(n)慢得多。
常见时间复杂度(从快到慢):
| 符号 | 名称 | 例子 |
|---|---|---|
| O(1) | 常数阶 | 数组随机访问 |
| O(log n) | 对数阶 | 二分查找 |
| O(n) | 线性阶 | 简单查找 |
| O(n log n) | 线性对数阶 | 快速排序 |
| O(n²) | 平方阶 | 冒泡排序 |
| O(2ⁿ) | 指数阶 | 斐波那契递归 |
你想想看,如果你的数据量是100万,O(n²)的算法要跑1万亿次操作,而O(n log n)只要2000万次。差距就是这么恐怖。
1.3.2 空间复杂度
空间复杂度,就是算法占用的内存大小。有些算法虽然快,但特别吃内存。比如用哈希表做缓存,速度快了,但内存占用也大了。
我曾经在嵌入式项目里吃过这个亏。嵌入式设备内存只有64KB,我写了个递归算法,递归深度一大,栈空间直接爆了。从那以后,我写算法都会先算算空间够不够。
避坑指南:我曾经在面试时遇到一个候选人,写了个时间复杂度O(1)的算法,但空间复杂度是O(n²)。我说你这算法在嵌入式设备上跑不了,他还不信。后来一测试,果然内存溢出。记住:时间和空间往往需要权衡,没有完美的算法。
1.4 知识体系总览
下面这张图,是我自己整理的算法基础知识体系。你看一遍,心里就有谱了:
1.5 一个简单的例子:求最大公约数
光说不练假把式。咱们用C语言写个经典算法——辗转相除法求最大公约数。这个算法我用了十几年,稳定可靠。
#include <stdio.h>
// 辗转相除法求最大公约数
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
int x = 48, y = 18;
printf("%d 和 %d 的最大公约数是 %d\n", x, y, gcd(x, y));
return 0;
}
这个算法的时间复杂度是O(log min(a,b)),空间复杂度是O(1)。你看,代码简单,效率还高。这就是好算法的样子。
我的习惯:写算法之前,先画个流程图,把思路理清楚。代码写起来就顺了。很多同学上来就写代码,写到一半发现逻辑不对,回头改更浪费时间。
1.6 总结一下
这一章咱们讲了算法的定义、五大特性、还有时间复杂度和空间复杂度。这些东西是算法的基本功,就像练武要先扎马步一样。
记住三点:
- 算法就是解决问题的步骤,要满足五个特性
- 时间复杂度看速度,空间复杂度看内存
- 没有完美的算法,要根据场景做取舍
下一章咱们开始讲具体的算法实现。先把基础打牢,后面学起来就轻松了。
公众号:蓝海资料掘金营,微信deep3321