NOI
NOICode
首页功能博客关于我们

学习资源

  • 博客
  • 学习指南
  • 备考攻略
  • 竞赛资讯

产品功能

  • 功能介绍
  • 价格方案
  • 常见问题
  • 更新日志

关于我们

  • 关于 NOI-Code
  • 联系我们
  • 合作伙伴

法律条款

  • 用户协议
  • 隐私政策
  • 服务条款

关注公众号

NOI
NOI-Code

AI 驱动的智能编程学习平台

© 2026 北京舞码科技有限公司

京ICP备2026015861号-1|京公网安备11011302007898号
Built withNOI-Code
首页/博客/算法复杂度速查手册
2026年5月20日·3 分钟阅读·NOI-Code 教研组算法基础知识算法复杂度复杂度分析

算法复杂度速查手册

本文是 OI Wiki - 复杂度简介 的整合精简版,所有示例均使用 C++。


1. 核心概念

概念说明
基本操作加减乘除、变量访问、赋值等,每次算一步
时间复杂度算法执行步骤数随输入规模 nnn 增长的趋势
空间复杂度算法占用内存随输入规模 nnn 增长的趋势
最坏复杂度所有可能输入中,用时最长的情况(竞赛中默认用这个)
平均复杂度所有可能输入下用时的平均值

为什么关注"趋势"而非"精确值"?
现代 CPU 每秒处理数亿次操作。
O(n2)O(n^2)O(n2) 的算法在 n=105n=10^5n=105 时需要 101010^{10}1010 次操作,直接超时;
O(nlog⁡n)O(n \log n)O(nlogn) 只需 ≈1.7×106\approx 1.7 \times 10^6≈1.7×106 次,轻松通过。趋势比常数系数更重要。


2. 渐近符号(大 O 家族)

符号类比含义何时用
Θ(g)\Theta(g)Θ(g)===上界 且 下界(紧确界)精确描述增长趋势
O(g)O(g)O(g)≤\le≤渐近上界描述最坏情况(最常用)
Ω(g)\Omega(g)Ω(g)≥\ge≥渐近下界证明算法不可能更快
o(g)o(g)o(g)<<<严格渐近上界数学分析(竞赛少用)
ω(g)\omega(g)ω(g)>>>严格渐近下界数学分析(竞赛少用)

记忆口诀:含"等于"用大写,不含等于用小写;相等是 Θ\ThetaΘ,小于是 OOO,大于是 Ω\OmegaΩ。

常用性质

f₁(n) + f₂(n)  = O(max(f₁, f₂))     // 取大的那个
f₁(n) × f₂(n)  = O(f₁ × f₂)         // 嵌套相乘
log_a(n)        = O(log n)            // 对数底数无所谓,可省略
f(n) = Θ(g(n)) ⟺ f = O(g) 且 f = Ω(g)

3. 复杂度计算实例

3.1 嵌套循环 → 相乘

int n, m;
std::cin >> n >> m;

for (int i = 0; i < n; ++i) {       // n 次
    for (int j = 0; j < n; ++j) {   // n 次
        for (int k = 0; k < m; ++k) // m 次
            std::cout << "hello\n";
    }
}
// 复杂度:Θ(n²m)

规则:嵌套循环各层次数相乘。


3.2 图的 DFS / BFS → 点 + 边

// 对 n 个点、m 条边的图做 DFS
void dfs(int u) {
    visited[u] = true;
    for (int v : graph[u])   // 每条边只走一次
        if (!visited[v]) dfs(v);
}
// 复杂度:Θ(n + m)

规则:每个节点和每条边各访问常数次 → O(n+m)O(n+m)O(n+m)。


3.3 常量循环 → O(1)

constexpr int N = 100000;  // N 是固定常量,与输入无关

for (int i = 0; i < N; ++i)
    std::cout << "hello\n";
// 复杂度:O(1)  —— N 不随输入变化,视为常数

关键:判断一个变量是否是"输入规模"。与输入无关的量都是常量,当 1 处理。


4. 主定理(Master Theorem)

用于快速求递归算法的复杂度。

适用形式:T(n)=a⋅T(n/b)+f(n)T(n) = a \cdot T(n/b) + f(n)T(n)=a⋅T(n/b)+f(n),其中 a≥1, b>1a \ge 1,\ b > 1a≥1, b>1。

情况条件结论
情况 1f(n)=O(nlog⁡ba−ε)f(n) = O(n^{\log_b a - \varepsilon})f(n)=O(nlogb​a−ε),ε>0\varepsilon > 0ε>0T(n)=Θ(nlog⁡ba)T(n) = \Theta(n^{\log_b a})T(n)=Θ(nlogb​a)
情况 2f(n)=Ω(nlog⁡ba+ε)f(n) = \Omega(n^{\log_b a + \varepsilon})f(n)=Ω(nlogb​a+ε),且满足正则条件T(n)=Θ(f(n))T(n) = \Theta(f(n))T(n)=Θ(f(n))
情况 3f(n)=Θ(nlog⁡ba⋅log⁡kn)f(n) = \Theta(n^{\log_b a} \cdot \log^k n)f(n)=Θ(nlogb​a⋅logkn),k≥0k \ge 0k≥0T(n)=Θ(nlog⁡ba⋅log⁡k+1n)T(n) = \Theta(n^{\log_b a} \cdot \log^{k+1} n)T(n)=Θ(nlogb​a⋅logk+1n)

正则条件(情况 2 需满足):a⋅f(n/b)≤c⋅f(n)a \cdot f(n/b) \le c \cdot f(n)a⋅f(n/b)≤c⋅f(n),对某常数 c<1c < 1c<1 且足够大的 nnn 成立。

速查示例

递推式aaabbblog⁡ba\log_b alogb​a适用情况结论
T(n)=2T(n/2)+1T(n) = 2T(n/2) + 1T(n)=2T(n/2)+1221情况 1Θ(n)\Theta(n)Θ(n)
T(n)=T(n/2)+nT(n) = T(n/2) + nT(n)=T(n/2)+n120情况 2Θ(n)\Theta(n)Θ(n)
T(n)=T(n/2)+log⁡nT(n) = T(n/2) + \log nT(n)=T(n/2)+logn120情况 3,k=1k=1k=1Θ(log⁡2n)\Theta(\log^2 n)Θ(log2n)
T(n)=T(n/2)+1T(n) = T(n/2) + 1T(n)=T(n/2)+1120情况 3,k=0k=0k=0Θ(log⁡n)\Theta(\log n)Θ(logn)

对应算法举例

// 归并排序:T(n) = 2T(n/2) + n  → Θ(n log n)  [情况 3, k=0]
void mergeSort(int* arr, int l, int r) {
    if (l >= r) return;
    int mid = (l + r) / 2;
    mergeSort(arr, l, mid);     // T(n/2)
    mergeSort(arr, mid+1, r);   // T(n/2)
    merge(arr, l, mid, r);      // O(n)
}

// 二分查找:T(n) = T(n/2) + 1  → Θ(log n)  [情况 3, k=0]
int binarySearch(int* arr, int l, int r, int target) {
    if (l > r) return -1;
    int mid = (l + r) / 2;
    if (arr[mid] == target) return mid;
    if (arr[mid] < target)  return binarySearch(arr, mid+1, r, target);
    return binarySearch(arr, l, mid-1, target);
}

5. 常见复杂度对比

从快到慢排列(n=106n = 10^6n=106 时的量级参考):

复杂度名称n=106n=10^6n=106 时操作数典型算法
O(1)O(1)O(1)常数1哈希表查找
O(log⁡n)O(\log n)O(logn)对数≈20\approx 20≈20二分查找
O(n)O(\sqrt{n})O(n​)平方根≈1000\approx 1000≈1000分块、质因数分解
O(n)O(n)O(n)线性10610^6106线性扫描、DFS/BFS
O(nlog⁡n)O(n \log n)O(nlogn)线性对数≈2×107\approx 2 \times 10^7≈2×107归并排序、堆排序
O(n2)O(n^2)O(n2)平方101210^{12}1012 ❌冒泡排序、朴素 DP
O(2n)O(2^n)O(2n)指数—暴力枚举子集

竞赛经验:10810^8108 次操作约耗时 1 秒。n≤106n \le 10^6n≤106 时,O(nlog⁡n)O(n \log n)O(nlogn) 通常安全;n≤104n \le 10^4n≤104 时才能用 O(n2)O(n^2)O(n2)。


6. 快速判断方法

循环嵌套?  → 各层次数相乘
顺序执行?  → 取复杂度最大的那段
递归分治?  → 套主定理
图算法?    → 通常 O(n + m) 或 O(m log n)
常量次操作?→ O(1)

参考来源:OI Wiki - 复杂度简介(CC BY-SA 4.0)

推荐阅读

5月21日·5 分钟

头文件与IO加速完全指南

NOI编译器
3月27日·2 分钟

排序算法详解:从冒泡到快速排序

算法排序
3月26日·3 分钟

二分查找:从原理到竞赛应用

算法二分查找

目录

  • 1. 核心概念
  • 2. 渐近符号(大 O 家族)
  • 常用性质
  • 3. 复杂度计算实例
  • 3.1 嵌套循环 → 相乘
  • 3.2 图的 DFS / BFS → 点 + 边
  • 3.3 常量循环 → O(1)
  • 4. 主定理(Master Theorem)
  • 速查示例
  • 对应算法举例
  • 5. 常见复杂度对比
  • 6. 快速判断方法