知识点1 时间复杂度、空间复杂度

文章目录

    • [1. 大O表示法(Big O Notation)](#1. 大O表示法(Big O Notation))
    • [2. 时间复杂度计算步骤](#2. 时间复杂度计算步骤)
      • [2.1 常见复杂度等级(从快到慢)](#2.1 常见复杂度等级(从快到慢))
    • [3. 时间复杂度具体示例(Java)](#3. 时间复杂度具体示例(Java))
      • [例1:常数阶 O(1)](#例1:常数阶 O(1))
      • [例2:线性阶 O(n)](#例2:线性阶 O(n))
      • [例3:平方阶 O(n²)](#例3:平方阶 O(n²))
      • [例4:对数阶 O(log n)](#例4:对数阶 O(log n))
      • [例5:递归(斐波那契) O(2ⁿ)](#例5:递归(斐波那契) O(2ⁿ))
    • [4. 空间复杂度计算](#4. 空间复杂度计算)
      • [示例1:O(1) 空间](#示例1:O(1) 空间)
      • [示例2:O(n) 空间](#示例2:O(n) 空间)
      • [示例3:递归栈空间 O(n)](#示例3:递归栈空间 O(n))
    • [5. 练习建议](#5. 练习建议)

1. 大O表示法(Big O Notation)

大O表示法描述算法性能的上界,忽略低阶项和常数系数,只保留增长最快的部分。

  • 一个循环执行 n 次 → O(n)
  • 双重循环各执行 n 次 → O(n²)
  • 常数个操作 → O(1)

2. 时间复杂度计算步骤

  1. 找出基本操作(循环、递归、数组访问等最内层的操作)。
  2. n 表示基本操作的执行次数。
  3. 使用大O表示:保留最高次项,去除系数和常数。

2.1 常见复杂度等级(从快到慢)

表示法 名称 典型场景(Java代码示意)
O(1) 常数阶 数组取值、简单算术
O(log n) 对数阶 二分查找
O(n) 线性阶 单层循环
O(n log n) 线性对数阶 归并排序、堆排序
O(n²) 平方阶 双层循环(冒泡排序)
O(2ⁿ) 指数阶 无剪枝递归(斐波那契)
O(n!) 阶乘阶 全排列的暴力解法

3. 时间复杂度具体示例(Java)

例1:常数阶 O(1)

java 复制代码
public int sumFirstTwo(int[] arr) {
    return arr[0] + arr[1];   // 只执行固定次数的加法,与数组长度n无关
}

分析 :无论数组多大,都只执行几次操作 → O(1)

例2:线性阶 O(n)

java 复制代码
public int findMax(int[] arr) {
    int maxVal = arr[0];
    for (int num : arr) {      // 循环 n 次
        if (num > maxVal) {
            maxVal = num;
        }
    }
    return maxVal;
}

分析 :循环次数 = nO(n)

例3:平方阶 O(n²)

java 复制代码
public void bubbleSort(int[] arr) {
    int n = arr.length;
    for (int i = 0; i < n; i++) {            // 外层 n 次
        for (int j = 0; j < n - i - 1; j++) { // 内层约 n/2 次
            if (arr[j] > arr[j + 1]) {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

分析 :比较次数 ≈ n*(n-1)/2 → 最高次项 O(n²)

例4:对数阶 O(log n)

java 复制代码
public int binarySearch(int[] arr, int target) {
    int left = 0, right = arr.length - 1;
    while (left <= right) {                 // 每次范围缩小一半
        int mid = left + (right - left) / 2;
        if (arr[mid] == target) {
            return mid;
        } else if (arr[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    return -1;
}

分析 :每次循环将查找区间减半,最坏需要 log₂(n) 次 → O(log n)

例5:递归(斐波那契) O(2ⁿ)

java 复制代码
public int fib(int n) {
    if (n <= 1) {
        return n;
    }
    return fib(n - 1) + fib(n - 2);
}

分析 :画出递归树,每个节点分出两个子节点,调用总数 ≈ 2ⁿO(2ⁿ)(极差)。

优化 :使用记忆化(动态规划)可降到 O(n)

4. 空间复杂度计算

空间复杂度衡量算法额外占用的内存(输入数据本身不计入)。同样用大O表示。

常见情况:

  • O(1) :只用了固定数量的变量(如几个 int、指针)。
  • O(n) :需要大小为 n 的数组、HashMap、递归栈等。
  • O(n²) :需要 n×n 的二维数组。

示例1:O(1) 空间

java 复制代码
public void reverseArray(int[] arr) {
    int left = 0, right = arr.length - 1;
    while (left < right) {
        int temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
        left++;
        right--;
    }
    // 只用了 left, right, temp 三个变量,不随 n 增长
}

示例2:O(n) 空间

java 复制代码
public int[] copyArray(int[] arr) {
    int[] newArr = new int[arr.length];   // 额外分配 n 个元素的数组
    for (int i = 0; i < arr.length; i++) {
        newArr[i] = arr[i];
    }
    return newArr;
}

示例3:递归栈空间 O(n)

java 复制代码
public int factorial(int n) {
    if (n == 0) {
        return 1;
    }
    return n * factorial(n - 1);
}

分析 :递归深度为 n,系统栈需要保存 n 个调用帧 → 空间复杂度 O(n)。(迭代版本可做到 O(1))

5. 练习建议

  • 刷题时 主动分析 自己代码的复杂度,并对照官方题解。
  • 多写 Java 内置数据结构 的操作:ArrayList.get/set → O(1);LinkedList.get → O(n);HashMap 平均 O(1) 等。
  • 理解不同算法在 Java 中的实现差异,例如递归 vs 迭代对空间复杂度的影响。

希望这篇博客对你有所帮助,也欢迎大家在评论区交流讨论!如果觉得有用,不妨点个赞支持一下 !感谢,共勉,祝好!😊

相关推荐
小小仙。2 小时前
IT自学第三十七天补充
java·开发语言
knight_9___2 小时前
RAG面试篇7
java·面试·agent·rag·智能体
博界IT精灵2 小时前
森林和二叉树的转换(哈喜老师)
数据结构
song8546011342 小时前
idea问题解决
java·ide·intellij-idea
问水っ2 小时前
Qt高级编程 第7章 用QtConcurrent实现线程处理
java·开发语言
啊我不会诶2 小时前
Codeforces Round 1093 (Div. 2)vp补题
算法
SimonKing2 小时前
AI编程工具装了一大堆,Skills 管理乱成粥?这个开源神器一招搞定!
java·后端·程序员
算法即正义2 小时前
知识竞赛音乐推荐:从开场抢答到颁奖环节的背景音乐选择指南
算法·职场和发展·学习方法
one_love_zfl2 小时前
java面试-微服务篇
java·微服务·面试