Skip to content

什么是算法

想象你第一次去一个陌生的城市,需要从火车站到酒店。你会怎么做?

你可能会打开手机地图,输入目的地,然后按照导航一步步走。导航软件告诉你:向前走 200 米,左转,直行 500 米,右转……这一系列明确的、有顺序的指令,其实就是一个「算法」。

算法并不神秘。它就是解决问题的步骤

算法的定义

我们先给出一个通俗的定义:

算法是解决特定问题的一系列明确步骤。

如果要更正式一点,可以这样描述:

算法是一个有限的、明确的、有效的指令序列,用于解决某一类问题或执行某个计算任务。

可以用一个简单的模型来理解:

┌─────────┐    ┌─────────────┐    ┌─────────┐
│  输入   │ →  │   算法处理   │ →  │  输出   │
│ (Input) │    │ (Algorithm) │    │ (Output)│
└─────────┘    └─────────────┘    └─────────┘

比如「在一组数中找最大值」这个问题:

  • 输入:一组数字 [3, 7, 2, 9, 5]
  • 算法:逐个比较,记录当前最大值
  • 输出:最大值 9

算法的五个特性

一个合格的算法必须具备以下五个特性。这不是什么高深的理论,而是非常朴素的要求。

1. 有穷性(Finiteness)

算法必须在有限步骤内终止。

这个要求看起来理所当然,但在实际编程中,无限循环是一个常见的 bug。

javascript
// ✅ 正例:有穷的算法
function findMax(arr) {
    let max = arr[0];
    for (let i = 1; i < arr.length; i++) {  // 有限次循环
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;  // 必定终止
}

// ❌ 反例:无穷循环(不是算法)
function infiniteLoop() {
    while (true) {  // 永不终止
        console.log("running...");
    }
}

2. 确定性(Definiteness)

每一步都有明确的含义,不能有歧义。

「差不多」「大概」这种模糊的描述不能出现在算法中。

javascript
// ✅ 正例:明确的指令
if (a > b) {
    return a;
}

// ❌ 反例:模糊的描述(伪代码)
// "如果 a 比 b 大一些,返回 a"
// 什么叫"大一些"?这就是歧义

3. 可行性(Feasibility)

每一步都能在有限时间内完成。

不能要求执行者做不可能完成的事情。

javascript
// ✅ 正例:可行的操作
const sum = a + b;  // 加法可以在有限时间完成

// ❌ 反例:不可行的操作(伪代码)
// "穷举所有实数"——实数有无穷多个,无法完成

4. 输入(Input)

零个或多个输入。

是的,可以是零个。比如生成一个固定的随机数序列,不需要任何输入。

javascript
// 有输入的算法
function add(a, b) {
    return a + b;
}

// 无输入的算法
function getCurrentTime() {
    return Date.now();
}

5. 输出(Output)

一个或多个输出。

这是必须的。一个没有输出的算法是没有意义的——你执行了一堆操作,却不告诉别人结果,有什么用呢?

javascript
// ✅ 正例:有输出
function square(n) {
    return n * n;  // 返回计算结果
}

// ❌ 反例:无输出(虽然语法正确,但作为算法没意义)
function doNothing(n) {
    const result = n * n;
    // 没有 return,调用者得不到任何结果
}

算法与程序的关系

很多初学者会把算法和程序混为一谈。它们有联系,但不是一回事。

对比项算法程序
本质解决问题的思想和步骤算法的具体实现
语言可以用自然语言、伪代码、流程图描述必须用编程语言编写
依赖与编程语言无关依赖特定的编程语言和平台
有穷性必须在有限步内终止可以是常驻运行的(如服务器)

一个关键的认知是:先有算法,后有程序

当你面对一个编程问题时,正确的流程是:

  1. 理解问题
  2. 设计算法(想清楚步骤)
  3. 用代码实现算法

很多人直接跳到第 3 步,上来就写代码,写着写着发现思路不对,又推倒重来。这就是没有「算法思维」的表现。

同样的算法,可以用不同的语言实现。比如「冒泡排序」这个算法,你可以用 JavaScript 写,也可以用 Python 写,甚至可以用 C 写。语言不同,但算法思想是一样的。

javascript
// JavaScript 版本
function bubbleSort(arr) {
    for (let i = 0; i < arr.length - 1; i++) {
        for (let j = 0; j < arr.length - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
            }
        }
    }
    return arr;
}
python
# Python 版本
def bubble_sort(arr):
    for i in range(len(arr) - 1):
        for j in range(len(arr) - 1 - i):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

两段代码做的事情完全一样,因为它们实现的是同一个算法。

为什么学习算法

你可能会问:现在有那么多现成的库和框架,为什么还要学习算法?

1. 面试必备

这是最现实的原因。几乎所有大厂的技术面试都会考察算法。LeetCode 刷题已经成为求职的「标准动作」。

2. 培养解决问题的能力

算法不仅仅是「背题」。学习算法的过程,是在训练你系统化思考问题的能力。这种能力在任何技术领域都是通用的。

3. 性能优化

同样的问题,不同的算法可能有天壤之别的效率。

举个例子:在 100 万个数中查找一个数。

  • 线性查找:最坏情况需要比较 100 万次
  • 二分查找(前提是数组有序):最多只需要比较 20 次

两者的差距是 5 万倍。当数据量更大时,差距会更加惊人。

4. 职业发展

初级程序员写代码,高级程序员设计算法。如果你想突破「码农」的天花板,算法能力是绕不过去的。

本章小结

本章我们认识了算法的基本概念:

  1. 算法是解决特定问题的一系列明确步骤
  2. 算法必须具备五个特性:有穷性、确定性、可行性、输入、输出
  3. 算法是思想,程序是实现——先想清楚步骤,再写代码
  4. 学习算法能帮助你通过面试、培养思维、优化性能、提升职业竞争力

既然算法有好坏之分,那么如何衡量一个算法的效率呢?这就是下一章要讨论的内容——时间复杂度分析

什么是算法 has loaded