算法如何随输入规模扩展:拆解 Big-O

发布: (2026年2月23日 GMT+8 10:16)
3 分钟阅读
原文: Dev.to

Source: Dev.to

Big‑O 表示法

“O” 代表 “order of”,用于描述算法的时间或空间需求随输入规模 n 增大时的上界(最坏情况)增长率。

计算时间复杂度

确定输入

找出什么是输入并用 n 表示其规模。

function sumArray(arr) {
    let sum = 0;
    for (let i = 0; i < arr.length; i++) {
        sum += arr[i];
    }
}

此处,n = arr.length

统计循环内部的操作

关注出现次数最多的操作。

简单 for 循环

for (let i = 0; i < n; i++) {
    // ...
}

O(n)

嵌套循环

for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
        // ...
    }
}

O(n²)

输入规模减半的循环(二分查找模式)

while (low <= high) {
    mid = Math.floor((low + high) / 2);
    // ...
}

O(log n)

递归调用(例如阶乘)

function factorial(n) {
    if (n === 0) return 1;
    return n * factorial(n - 1);
}

O(n)(阶乘函数本身的递归调用次数是线性的;原文中 “n log n” 的标注是错误的)

简化表达式

  • O(3n + 10)O(n)
  • O(n² + n)O(n²)

常见时间复杂度

复杂度描述
O(1)常数时间——执行时间不随输入规模变化。
O(log n)对数时间——典型于二分查找;每一步将问题规模减半。
O(n)线性时间——对输入进行一次遍历。
O(n log n)线性对数时间——常见于高效排序算法(如归并排序、堆排序)。
O(n²)二次时间——对相同规模的输入进行嵌套循环。
O(n³)三次时间——三个嵌套循环。
O(2ⁿ)指数时间——每个元素产生两个递归调用(例如朴素递归实现的斐波那契)。
O(n!)阶乘时间——输入的全排列(例如暴力求解的旅行商问题)。

复杂度的有序列表(从快到慢)

O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2ⁿ) < O(n!)

理解时间复杂度对于编写高效且可扩展的代码至关重要。通过使用 Big‑O 表示法,你可以分析算法的性能随输入规模的变化,并据此做出选择,以决定采用哪种方案。在设计和优化程序时,请牢记这些复杂度。

0 浏览
Back to Blog

相关文章

阅读更多 »

前缀和:入门

欢迎来到我的算法之旅!如果你曾经看过一个编码挑战并感觉自己在盯着一堵砖墙,你并不孤单。大多数的ti...

停止在 Rails 中错误使用 .any?

介绍:传递给 .any? 的单个块可能会在不发出警告或错误的情况下,悄悄将成千上万条记录加载到内存中——仅仅是产生不必要的对象。大多数 Rails 开发者……