算法之空间复杂度

111 阅读2分钟

空间复杂度

  1. 常量空间

    当算法的存储空间大小固定,和输入规模没有直接的关系时,空间复杂度记作 O(1)O(1)

    void fun1(int n){
       int var = 3;
       ...
    }
    
  2. 线性空间

​ 当算法分配的空间是一个线性的集合(如数组),并且集合大小和输入规模n成正比时,空间复杂度 O(n)O(n)

void fun2(int n){
 int[] array = new int[n];
}
  1. 二维空间

    当算法分配的空间是一个二维数组集合,并且集合的长度和宽度都与输入规模n成正比时,空间复杂度记作 O(n2)O(n^2)

void fun3(int n){
   int[][] matrix = new int[n][n];
}
  1. 递归空间

递归是一个比较特殊的场景。虽然递归代码中并没有显示地声明变量或集合,但是计算机在执行程序时,会专门分配一块内存,用来存储 "方法调用栈"。

“方法调用栈” 包括 进栈 和出栈 两个行为。

当进入一个新方法时,执行入栈操作,把调用的方法和参数信息压入栈中。

当方法返回时,执行出栈操作,把调用的方法和参数信息从栈中弹出。

void fun4(int n){
    if(n<=1){
      return;
    } 
    fun4(n-1);
    ...
}

假如初始传入参数值n=5, 那么方法 fun4 (参数n=5) 的调用信息陷入栈

image-20210405151353113

接下来递归调用相同的方法,方法 fun4 (参数 n=4) 的调用信息入栈

image-20210405151527759

以此类推,递归越来越深,入栈的元素就越来越多

image-20210405151759239

当 n=1 时,达到递归结束条件,执行 return 指令,方法出栈。

最终 ,方法调用栈 的全部元素会一一出栈。

由上面 方法调用栈 的出入栈过程可以看出,执行递归操作所需要的内存空间和递归的深度成正比。纯粹的递归操作的空间复杂度也是线性的,如果递归的深度是n,那么空间的复杂度是 O(n)O(n)

参考

《漫画算法》