时间和空间复杂程度计算规则

时间复杂度和空间复杂度的计算是算法分析的重要部分。以下是详细的计算方法、示例,以及需要注意的要点。


1. 时间复杂度

时间复杂度描述算法执行所需时间随输入规模增长的增长关系,通常用 大 O O O 表示法 来表示,关注输入规模 n n n 的增长率。


1.1 时间复杂度的计算方法

  1. 找到最内层操作

    • 确定算法中执行次数最多的基本操作(如赋值、比较、加法等)。
  2. 统计执行次数

    • 从外到内,计算循环、递归或逻辑分支中基本操作的执行次数。
  3. 保留最高阶

    • 只保留执行次数随输入规模 n n n 增长最快的部分,忽略低次项和常数系数。

1.2 常见时间复杂度

  1. 常数时间: O ( 1 ) O(1) O(1)

    • 不依赖于输入规模,执行次数恒定。
    c 复制代码
    int a = 10;
    a = a + 1; // 常数时间
  2. 线性时间: O ( n ) O(n) O(n)

    • 基本操作执行次数与输入规模 n n n成正比。
    c 复制代码
    for (int i = 0; i < n; i++) {
        printf("%d\n", i); // 执行 n 次
    }
  3. 平方时间: O ( n 2 ) O(n^2) O(n2)

    • 嵌套循环中,每个循环迭代 n n n次,基本操作执行 n 2 n^2 n2次。
    c 复制代码
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%d, %d\n", i, j); // 执行 n * n 次
        }
    }
  4. 对数时间: O ( log ⁡ n ) O(\log n) O(logn)

    • 规模每次减小一半,通常出现在二分查找等算法中。
    c 复制代码
    while (low <= high) {
        mid = (low + high) / 2;
        if (arr[mid] == target)
            return mid;
        else if (arr[mid] < target)
            low = mid + 1;
        else
            high = mid - 1;
    }
  5. 线性对数时间: O ( n log ⁡ n ) O(n \log n) O(nlogn)

    • 通常出现在分治算法(如归并排序)。
    c 复制代码
    void mergeSort(int arr[], int n) {
        if (n <= 1) return;
        int mid = n / 2;
        mergeSort(left, mid);
        mergeSort(right, n - mid);
        merge(left, right, arr); // 合并操作执行 O(n)
    }
  6. 指数时间: O ( 2 n ) O(2^n) O(2n)

    • 通常出现在递归枚举(如穷举法)。
    c 复制代码
    void subset(int[] arr, int n) {
        if (n == 0) return;
        subset(arr, n - 1);
        subset(arr + [arr[n]], n - 1); // 分成两种选择
    }

1.3 示例:时间复杂度的具体分析

示例 1:
c 复制代码
for (int i = 0; i < n; i++) {
    printf("%d\n", i);
}
  • 基本操作:printf
  • 执行次数: n n n。
  • 时间复杂度: O ( n ) O(n) O(n)。
示例 2:
c 复制代码
for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
        printf("%d, %d\n", i, j);
    }
}
  • 基本操作:printf
  • 执行次数:外层循环执行 n n n次,内层循环每次执行 n n n次,总共 n × n = n 2 n \times n = n^2 n×n=n2 次。
  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)。
示例 3:
c 复制代码
int i = 1;
while (i <= n) {
    i *= 2;
}
  • 基本操作:i *= 2
  • 执行次数:每次迭代 i i i乘 2,最多执行 l o g 2 n log_2 n log2n 次。
  • 时间复杂度: O ( log ⁡ n ) O(\log n) O(logn)。

2. 空间复杂度

空间复杂度描述算法运行时使用的额外内存随输入规模增长的关系,也用 大 O 表示法 表示。


2.1 空间复杂度的计算方法

  1. 统计额外变量

    • 计算算法使用的变量、数组、递归栈的大小。
  2. 输入空间不计入

    • 输入数组或数据结构的存储空间不属于额外空间。
  3. 递归调用的栈空间

    • 如果算法有递归,递归栈的深度乘以每层所需空间。

2.2 常见空间复杂度

  1. 常数空间: O ( 1 ) O(1) O(1)

    • 使用固定数量的变量,无论输入规模如何。
    c 复制代码
    int a = 0;
    a++;
  2. 线性空间: O ( n ) O(n) O(n)

    • 使用额外的数组或数据结构,大小与输入规模 n n n成正比。
    c 复制代码
    int* temp = (int*)malloc(n * sizeof(int));
  3. 递归栈空间: O ( n ) O(n) O(n)

    • 深度为 n n n的递归会使用 O ( n ) O(n) O(n) 的栈空间。
    c 复制代码
    void recursive(int n) {
        if (n == 0) return;
        recursive(n - 1);
    }

2.3 示例:空间复杂度的具体分析

示例 1:
c 复制代码
int sum = 0;
for (int i = 0; i < n; i++) {
    sum += i;
}
  • 使用的额外变量:sumi,总共占用固定空间。
  • 空间复杂度: O ( 1 ) O(1) O(1)。
示例 2:
c 复制代码
int* temp = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
    temp[i] = i;
}
  • 使用的额外空间:长度为 n n n的数组 temp
  • 空间复杂度: O ( n ) O(n) O(n)。
示例 3:
c 复制代码
void recursive(int n) {
    if (n == 0) return;
    recursive(n - 1);
}
  • 每次递归调用都会占用一个栈帧。
  • 如果递归深度为 n n n,栈空间总大小为 O ( n ) O(n) O(n)。

3. 时间复杂度和空间复杂度的对比

算法类型 时间复杂度 空间复杂度
直接循环 O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)
嵌套循环 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)
递归算法 O ( 2 n ) O(2^n) O(2n) O ( n ) O(n) O(n)
分治算法 O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( n ) O(n) O(n)
动态规划 O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2)

总结

  • 时间复杂度
    • 根据基本操作的执行次数,分析循环、分支、递归的增长趋势。
  • 空间复杂度
    • 根据额外变量、数组、递归栈的大小,估算内存使用的增长关系。

理解和计算复杂度需要结合实际代码逐行分析,尤其要关注循环和递归结构的执行规律。

相关推荐
·云扬·4 小时前
Java IO 与 BIO、NIO、AIO 详解
java·开发语言·笔记·学习·nio·1024程序员节
Tisfy4 小时前
LeetCode 3240.最少翻转次数使二进制矩阵回文 II:分类讨论
算法·leetcode·矩阵·题解·回文·分类讨论
求积分不加C4 小时前
Spring Boot中使用AOP和反射机制设计一个的幂等注解(两种持久化模式),简单易懂教程
java·spring boot·后端
枫叶_v4 小时前
【SpringBoot】26 实体映射工具(MapStruct)
java·spring boot·后端
橘子遇见BUG4 小时前
算法日记 31 day 动态规划(01背包)
算法·动态规划
东方巴黎~Sunsiny4 小时前
java-图算法
java·开发语言·算法
ac-er88885 小时前
PHP二维数组排序算法函数
算法·php·排序算法
Tisfy5 小时前
LeetCode 3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))
算法·leetcode·题解·贪心·思维
2401_857617625 小时前
汽车资讯新趋势:Spring Boot技术解读
java·spring boot·后端
小林学习编程6 小时前
从零开始理解Spring Security的认证与授权
java·后端·spring