时间复杂度和空间复杂度是衡量算法效率的核心指标,均采用大O符号(Big O)**表示,描述算法性能随输入规模(n)增长的变化趋势。
目录
[O(1) 常数阶](#O(1) 常数阶)
[O(n) 线性阶](#O(n) 线性阶)
[O(n²) 平方阶](#O(n²) 平方阶)
[O(log n) 对数阶](#O(log n) 对数阶)
[O(n log n) 线性对数阶](#O(n log n) 线性对数阶)
[O(1) 常数阶](#O(1) 常数阶)
[O(n) 线性阶](#O(n) 线性阶)
[O(n²) 平方阶](#O(n²) 平方阶)
[O(n) 递归栈空间](#O(n) 递归栈空间)
时间复杂度
衡量代码执行时间随数据规模增长的变化趋势。
O(1) 常数阶
执行次数固定,与输入规模无关。
c
int constantTime(int n) {
int a = 10;
int b = 20;
return a + b;
}
- 特点:执行时间恒定,不受输入规模影响,效率最优。
O(n) 线性阶
执行次数与输入规模成正比。
c
void linearTime(int n) {
for (int i = 0; i < n; i++) {
printf("当前数字: %d\n", i);
}
}
- 特点:常见于单层循环或数组遍历。
O(n²) 平方阶
执行次数与n的平方成正比。
c
void quadraticTime(int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("坐标: (%d, %d)\n", i, j);
}
}
}
- 特点:常见于双重嵌套循环(如冒泡排序),n较大时性能急剧下降。
O(log n) 对数阶
每次执行缩减问题规模(如减半)。
c
void logarithmicTime(int n) {
for (int i = 1; i < n; i *= 2) {
printf("当前数字: %d\n", i);
}
}
- 特点:效率极高,常见于二分查找或分治算法。
O(n log n) 线性对数阶
结合线性与对数增长。
c
void nLogNExample(int n) {
for (int i = 0; i < n; i++) {
for (int j = 1; j < n; j *= 2) {
// 执行操作
}
}
}
- 特点:常见于高效排序算法(如归并排序)。
空间复杂度
衡量算法运行中额外申请的内存空间(不含输入数据本身)。
O(1) 常数阶
仅使用固定数量的变量。
c
void constantSpace(int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += i;
}
}
O(n) 线性阶
额外空间与输入规模成正比。
c
void linearSpace(int n) {
int* arr = (int*)malloc(n * sizeof(int));
free(arr);
}
O(n²) 平方阶
额外空间随n呈平方增长(如二维数组)。
c
void quadraticSpace(int n) {
int** matrix = (int**)malloc(n * sizeof(int*));
for (int i = 0; i < n; i++) {
matrix[i] = (int*)malloc(n * sizeof(int));
}
}
O(n) 递归栈空间
递归深度决定空间复杂度。
c
void recursiveSpace(int n) {
if (n <= 0) return;
recursiveSpace(n - 1);
}
复杂度对比
| 复杂度 | 名称 | 增长趋势 | 典型场景 | 性能评价 |
|---|---|---|---|---|
| O(1) | 常数阶 | 恒定 | 数组访问 | 最优 |
| O(log n) | 对数阶 | 极缓慢 | 二分查找 | 优秀 |
| O(n) | 线性阶 | 线性增长 | 单层循环 | 良好 |
| O(n log n) | 线性对数阶 | 较缓慢 | 归并排序 | 较好 |
| O(n²) | 平方阶 | 快速增长 | 冒泡排序 | 一般 |
| O(2ⁿ) | 指数阶 | 指数爆炸 | 暴力穷举 | 较差 |
实际应用权衡
- 时间换空间:优化内存使用,但增加计算时间。
- 空间换时间:通过缓存或预计算提升速度,但占用更多内存。
总结
- 时间复杂度反映执行时间的增长趋势。
- 空间复杂度反映内存使用的增长趋势。
- 选择算法需综合两者,通常需权衡时间与空间效率。
- 理解复杂度对编写高效代码至关重要。