算法衡量占用空间大小:空间复杂度 作者:马育民 • 2026-02-01 17:21 • 阅读:10003 # 介绍 **空间复杂度(Space Complexity)** 是算法分析中的核心概念,用于衡量算法在运行过程中 **临时占用存储空间大小的量级**,反映算法对内存资源的消耗程度,通常用**大O符号(Big O Notation)** 表示。 # 定义 空间复杂度是对算法运行时,除输入数据本身占用的空间外,**额外开辟的辅助空间**随输入规模 `n` 增长的变化趋势,不包含输入、输出数据的原始存储空间,仅关注算法执行所需的临时空间(如变量、数组、栈帧、动态分配内存等)。 ### 计算规则 推导时只关注**增长最快的项**,忽略低阶项、常数系数、常数项,因为这些在输入规模 $$n$$ 极大时,对内存占用的影响可以忽略: 1. 忽略 **常数项**:开辟3个临时变量,空间复杂度为 $$O(1)$$(而非 $$O(3)$$ ); 2. 忽略 **常数系数**:开辟 $$2n$$ 个大小的数组,空间复杂度为$$O(n)$$(而非$$O(2n)$$); 3. 忽略 **低阶项**:开辟 $$n+5$$ 个空间,复杂度为 $$O(n)$$(5是低阶常数项); 4. 关注 **与输入规模 $$n$$ 相关的空间**:只有新开辟的空间数量随 $$n$$ 变化时,才会影响复杂度等级。 # 常见算法的空间复杂度 | 算法 | 空间复杂度 | 备注 | |--------------|------------|--------------------------| | 冒泡排序 | O(1) | 仅用临时变量交换,原地排序 | | 快速排序 | O(log n)~O(n) | 递归栈空间,最优O(log n) | | 归并排序 | O(n) | 需辅助数组合并数据 | | 二分查找 | O(1)(迭代)/ O(log n)(递归) | 无额外辅助空间 | | 哈希表查找 | O(n) | 需存储哈希表本身 | # 重点案例解析 ### 1. O(1) 常数空间(最常用) 算法执行中,**仅开辟固定数量的临时变量/指针**,无论输入规模 $$n$$ 多大,额外空间都不变。 ```java // 案例1:两数交换(仅用1个temp变量) public static void swap(int[] arr, int i, int j) { int temp = arr[i]; // 固定1个临时变量,与n无关 arr[i] = arr[j]; arr[j] = temp; } // 案例2:求数组和(仅用1个sum变量) public static int getSum(int[] arr) { int sum = 0; // 固定1个变量,无论arr多长,额外空间都不变 for (int num : arr) { sum += num; } return sum; } ``` **结论**:只要新开辟的空间数量是**固定值**,不管是1个还是100个,空间复杂度都是\(O(1)\)。 ### 2. O(n) 线性空间 算法执行中,**开辟了与输入规模 $$n$$ 成正比的新空间**(比如新数组、新集合)。 ```java // 案例:复制一个长度为n的数组(新开辟n个空间) public static int[] copyArr(int[] arr) { int n = arr.length; int[] newArr = new int[n]; // 新数组长度= n,额外空间随n线性增长 for (int i = 0; i < n; i++) { newArr[i] = arr[i]; } return newArr; } ``` **结论**:只要新开辟的空间数量**等于n/2n/3n**等,按规则忽略系数,复杂度都是\(O(n)\)。 ### 3. O(log n) 对数空间 额外空间随 $$n$$ 增长但**增长极慢**,典型场景就是**递归版算法的调用栈**(比如你刚学的递归版快速排序)。 后续会结合快排详细讲,核心逻辑:每次把问题分成两半,递归深度为 $$\log_2 n$$,栈空间随递归深度增长。 # 空间复杂度 vs 时间复杂度 | 维度 | 时间复杂度 | 空间复杂度 | |--------------|-----------------------------------|-----------------------------------| | 衡量目标 | 算法执行的**操作次数/耗时**随`n`的变化 | 算法执行的**临时空间占用**随`n`的变化 | | 核心关注点 | 运行速度 | 内存消耗 | | 优化优先级 | 通常优先优化时间复杂度 | 内存受限场景下优先优化空间复杂度 | ### 权衡 实际开发中,算法的**时间效率**和**空间效率**往往是**此消彼长**的,这就是经典的**时空权衡**思想: 1. **空间换时间**:牺牲更多的空间,换取更快的运行速度(比如用哈希表存数据,把查找时间从\(O(n)\)降到\(O(1)\)); 2. **时间换空间**:牺牲一点运行速度,换取更少的内存占用(比如为了节省空间,放弃哈希表,用线性查找)。 # 总结 1. 空间复杂度描述的是**额外辅助空间**的增长趋势,而非绝对空间大小; 2. 优先关注量级 `(O(1) < O(log n) < O(n) < O(n²) < O(2ⁿ))`,量级越小空间效率越高; 3. 实际开发中需**时空权衡**:有时用空间换时间(如缓存、哈希表),有时用时间换空间(如原地排序)。 原文出处:http://malaoshi.top/show_1GW2hPn5WEk0.html