时间复杂度和空间复杂度入门必备知识点

       本文从基础概率、计算方法、常见复杂度分类、详细计算的案例入手,带读者初步了解算法复杂度:时间复杂度衡量算法执行时间随数据规模n的增长趋势,空间复杂度衡量额外内存使用情况。二者都用大O表示法,忽略系数保留最高阶项。常见时间复杂度:常数O(1)、对数O(logn)、线性O(n)、线性对数O(nlogn)、平方O(n²)、指数O(2ⁿ)。计算时需找基本操作并建立T(n)表达式。空间复杂度分析额外变量和递归深度。典型案例:冒泡排序时间O(n²)空间O(1),归并排序时间O(nlogn)空间O(n)。优化需权衡时空效率,n较小时可用简单算法,大时需高效算法。注意理论复杂度与实际性能的差异。

Java实现10大经典排序算法-CSDN博客

目录

一、基本概念

二、计算方法

时间复杂度计算步骤:

空间复杂度计算步骤:

三、常见复杂度分类

时间复杂度增长趋势:

空间复杂度增长趋势:

四、详细计算案例

案例1:冒泡排序

案例2:归并排序

五、特殊规则

六、复杂度对比表

七、实用技巧


一、基本概念
  1. 时间复杂度

    • 衡量算法执行时间随数据规模增长的变化趋势

    • 不计算具体时间,关注增长量级

    • 用大O符号表示(O(f(n)))

  2. 空间复杂度

    • 衡量算法运行过程中临时占用内存空间随数据规模增长的变化趋势

    • 不包括原始数据存储空间

    • 同样用大O符号表示

二、计算方法
时间复杂度计算步骤:
  1. 找出基本操作(执行次数最多的语句)

  2. 计算执行次数T(n)关于数据规模n的表达式

  3. 保留最高阶项,去掉系数

示例分析

// 示例1:常数阶 O(1)
int a = 1; 
int b = 2;
int c = a + b; // 执行3次 → O(1)

// 示例2:线性阶 O(n)
for (int i = 0; i < n; i++) {  // 执行n次
    System.out.println(i);      // 执行n次
} // T(n) = 2n → O(n)

// 示例3:平方阶 O(n²)
for (int i = 0; i < n; i++) {          // 执行n次
    for (int j = 0; j < n; j++) {      // 执行n次
        System.out.println(i + j);      // 执行n²次
    }
} // T(n) = n² + n → O(n²)

// 示例4:对数阶 O(log n)
int i = 1;
while (i < n) {
    i = i * 2;   // 每次循环扩大2倍
} // 循环次数k:2^k = n → k = log₂n → O(log n)
空间复杂度计算步骤:
  1. 计算算法使用的额外空间(不包括输入数据)

  2. 分析空间使用与n的关系

  3. 保留最高阶项

示例分析

// 示例1:常数空间 O(1)
void bubbleSort(int[] arr) {
    int temp;  // 固定1个变量
    // ...     // 空间不随n变化
}

// 示例2:线性空间 O(n)
int[] copyArray(int[] arr) {
    int[] newArr = new int[arr.length];  // 开辟n大小的空间
    // ...
    return newArr;
}

// 示例3:递归空间 O(n)
int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);  // 递归深度n
} // 调用栈空间O(n)
三、常见复杂度分类
时间复杂度增长趋势:
  T(n)
  ↑
  │  O(2ⁿ)  → 指数级(不可接受)
  │   / 
  │  / O(n²) → 平方阶(慢)
  │ / /
  │/ / O(n log n) → 线性对数阶(较快)
  │ / /
  │/ / O(n) → 线性阶(良好)
  │ / /
  │/ / O(log n) → 对数阶(优秀)
  │ / /
  │/_/ O(1) → 常数阶(理想)
  └──────────────────→ n
空间复杂度增长趋势:
S(n)
  ↑
  │   O(n)
  │  /
  │ / 
  │/   O(log n)
  │   /
  │  / 
  │ / 
  │/  
  └───────────────→ n
  O(1)
四、详细计算案例
案例1:冒泡排序
void bubbleSort(int[] arr) {
    int n = arr.length;                  // O(1)空间
    for (int i = 0; i < n-1; i++) {      // 外循环n次
        for (int j = 0; j < n-i-1; j++) { // 内循环n-i次
            if (arr[j] > arr[j+1]) {     // 基本操作
                // 交换操作
                int temp = arr[j];       // O(1)临时空间
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}
  • 时间复杂度
    T(n) = (n-1) + (n-2) + ... + 1 = n(n-1)/2 → O(n²)

  • 空间复杂度:仅使用固定数量变量 → O(1)

案例2:归并排序
void mergeSort(int[] arr, int left, int right) {
    if (left < right) {
        int mid = (left + right) / 2;
        mergeSort(arr, left, mid);      // 递归左半
        mergeSort(arr, mid+1, right);   // 递归右半
        merge(arr, left, mid, right);   // 合并操作
    }
}

void merge(int[] arr, int left, int mid, int right) {
    int[] temp = new int[right - left + 1];  // 创建临时数组
    // ...合并操作...
}
  • 时间复杂度
    递归树深度 = log₂n,每层合并O(n) → O(n log n)

  • 空间复杂度
    递归栈深度O(log n) + 临时数组O(n) → O(n)

五、特殊规则
  1. 最坏/平均/最好复杂度

    • 最坏情况:输入数据最不利时(上界)

    • 平均情况:随机输入时期望值

    • 最好情况:输入数据最有利时(下界)

  2. 大O记号规则

    • 6n³ + 2n² + 20 → O(n³)

    • 200 → O(1)

    • 3log n + 2n → O(n)

  3. 递归复杂度分析
    使用主定理(Master Theorem)或递归树法

    T(n) = aT(n/b) + f(n)
六、复杂度对比表
复杂度 名称 n=100时的操作次数 常见算法
O(1) 常数阶 1 哈希查找
O(log n) 对数阶 7 二分查找、平衡树操作
O(n) 线性阶 100 遍历数组
O(n log n) 线性对数阶 700 快速排序、归并排序
O(n²) 平方阶 10,000 冒泡排序、选择排序
O(n³) 立方阶 1,000,000 矩阵乘法(朴素)
O(2ⁿ) 指数阶 1.26e+30 汉诺塔、穷举算法
O(n!) 阶乘阶 9.3e+157 旅行商问题(暴力解)
七、实用技巧
  1. 时间-空间权衡

    • 哈希表:用空间换时间(O(1)查询)

    • 递归改迭代:用时间换空间(避免栈溢出)

  2. 优化方向

    时间复杂度和空间复杂度入门必备知识点_第1张图片

  3. 实际应用原则

    • n<50:简单排序(插入排序)

    • 50

    • n>1000:O(n log n)排序

    • n>10⁶:考虑非比较排序(计数、基数排序)

重要提示:复杂度分析是理论模型,实际性能受常数因子、缓存命中率、硬件特性等影响。对于关键代码,应结合性能测试进行优化。

时间复杂度和空间复杂度入门必备知识点_第2张图片

你可能感兴趣的:(算法,算法,数据结构,java)