算法基础知识 - 03. 什么是空间复杂度

空间复杂度(Space Complexity)

空间复杂度是衡量算法在运行过程中临时占用存储空间(内存)随输入规模增长的变化趋势的指标。和时间复杂度类似,它也用大O符号(Big-O Notation)表示,关注的是额外空间的占用,不包括输入数据本身占用的空间。


为什么需要空间复杂度?

  1. 内存限制:计算机内存有限,算法占用空间过大会导致程序崩溃(如递归过深导致栈溢出)。
  2. 优化资源:在内存紧张的设备(如嵌入式系统、手机)中,需优先选择省空间的算法。
  3. 与时间复杂度权衡:有时可以用空间换时间(如哈希表),反之亦然。

常见空间复杂度类型(从低到高)

大O表示名称例子说明
O(1)常数空间变量交换、迭代计算只占用固定大小的额外空间
O(n)线性空间数组拷贝、递归调用栈空间与输入规模成正比
O(n²)平方空间二维矩阵、动态规划表空间随输入规模平方增长
O(log n)对数空间递归二分查找递归深度为log n(如分治算法)

如何计算空间复杂度?

  1. 关注额外空间:不包括输入数据本身占用的空间。
    • 例如:排序算法的输入是数组,但计算空间复杂度时不统计数组本身,只统计算法额外分配的变量、数组、递归栈等。
  2. 分析变量与数据结构
    • 基本变量(如int、float)算O(1)。
    • 动态分配的数据结构(如数组、哈希表)算O(n)。
  3. 递归调用:递归深度消耗的栈空间需计入。

经典例子分析

1. O(1) 常数空间
def swap(a, b):
    temp = a  # 仅用到一个临时变量temp,空间固定
    a = b
    b = temp
2. O(n) 线性空间
def copy_array(arr):
    new_arr = [0] * len(arr)  # 分配了一个与输入数组等长的新数组
    for i in range(len(arr)):
        new_arr[i] = arr[i]
    return new_arr
3. O(n²) 平方空间
def generate_matrix(n):
    matrix = [[0] * n for _ in range(n)]  # 分配n×n的二维矩阵
    return matrix
4. O(log n) 对数空间(递归)
def recursive_binary_search(arr, target, left, right):
    if left > right:
        return -1
    mid = (left + right) // 2
    if arr[mid] == target:
        return mid
    elif arr[mid] < target:
        return recursive_binary_search(arr, target, mid+1, right)  # 递归深度为log n
    else:
        return recursive_binary_search(arr, target, left, mid-1)

空间复杂度 vs 时间复杂度

  • 时间换空间:某些算法通过重复计算减少内存占用(如斐波那契数列的递归解法)。
  • 空间换时间:如哈希表通过预分配空间实现快速查找。
例子:斐波那契数列
# O(2ⁿ) 时间,O(1) 空间(尾递归优化前)
def fib(n):
    if n <= 1:
        return n
    return fib(n-1) + fib(n-2)

# O(n) 时间,O(n) 空间(动态规划)
def fib_dp(n):
    dp = [0, 1] + [0] * (n-1)
    for i in range(2, n+1):
        dp[i] = dp[i-1] + dp[i-2]
    return dp[n]

# O(n) 时间,O(1) 空间(优化版)
def fib_optimized(n):
    if n <= 1:
        return n
    a, b = 0, 1
    for _ in range(2, n+1):
        a, b = b, a + b
    return b

实际应用中的权衡

  1. 内存充足时:优先选择时间复杂度低的算法(如快速排序)。
  2. 内存紧张时:选择空间复杂度低的算法(如堆排序是原地排序,空间O(1))。
  3. 递归的陷阱:递归可能简洁但消耗栈空间(如树遍历的递归 vs 迭代实现)。

常见误区

  • 误区1:认为“原地算法”一定不需要额外空间。(实际可能仍需O(1)的临时变量)
  • 误区2:忽略递归调用的栈空间。(递归深度大时可能导致栈溢出)
  • 误区3:混淆输入空间和额外空间。(如输入数组不算在空间复杂度内)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值