一、算法概述:从菜鸟到老手的必修课

各位同学好,我是老张。今天咱们聊聊算法的基础概念。说实话,我教了这么多年C语言,发现很多同学一听到「算法」两个字就发怵。其实没必要,算法没那么玄乎。

先问大家一个问题:你平时写代码,是不是经常遇到「这个功能该怎么实现」的困惑?比如让你把一组数字从小到大排个序,或者从一堆数据里找出某个值。嗯,这些问题的解决方案,就是算法。

算法的本质:说白了,就是解决问题的步骤和方法。就像你做菜,先洗菜、再切菜、最后下锅炒——这就是一个算法。

1.1 算法的定义

算法(Algorithm)这个词,听起来高大上,其实老祖宗早就用了。中国古代的《九章算术》里就有很多算法。现代计算机科学里,算法的定义是:对特定问题求解步骤的一种描述

我个人习惯把算法理解成「菜谱」。菜谱告诉你先放油、再放葱姜蒜、最后下主料——算法告诉计算机先做什么、再做什么、最后输出什么结果。

1.2 算法的五大特性

一个合格的算法,必须满足五个条件。我在项目中吃过不少亏,有些就是算法设计不严谨导致的。咱们一个一个说:

  1. 有穷性——算法必须在有限步骤内结束。不能死循环,不能无限跑下去。我曾经见过一个排序算法,数据量一大就卡死,后来发现是递归没写终止条件。
  2. 确定性——每一步操作都必须明确,不能有歧义。比如「把数字变大点」这种描述就不行,到底变大多少?要写清楚。
  3. 可行性——算法中的每一步都必须能通过有限次基本运算实现。你不能写「直接算出宇宙的终极答案」,这做不到。
  4. 输入——算法可以有零个或多个输入。比如求1到100的和,就不需要外部输入。
  5. 输出——算法至少有一个输出。没有输出的算法,就像做了饭不给人吃,毫无意义。

小提示:写算法时,先检查这五个条件。尤其是「有穷性」,很多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 知识体系总览

下面这张图,是我自己整理的算法基础知识体系。你看一遍,心里就有谱了:

算法概述 算法定义 五大特性 算法复杂度 有穷性 确定性 可行性 输入 输出 时间复杂度 空间复杂度 O(1) 常数阶 O(log n) 对数阶 O(n) 线性阶 O(n²) 平方阶

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