时间复杂度
1. 什么是时间复杂度?
时间复杂度(Time Complexity)是计算算法执行时间随输入规模(n)增长的变化趋势。它衡量算法的效率,通常使用大 O 记号(Big-O notation)表示,忽略低阶项和常数系数。
2. 时间复杂度的用途
- 评估算法性能:帮助选择更高效的算法,提高程序执行速度。
- 预测程序运行时间:根据输入规模预估代码的执行时间。
- 优化代码:通过分析时间复杂度找到瓶颈,优化算法。
3. 常见时间复杂度及其排序
按照执行速度从快到慢排序如下:
时间复杂度 | 说明 | 示例 |
---|---|---|
O(1) | 常数时间 | 直接访问数组元素 arr[i] |
O(log n) | 对数时间 | 二分查找 |
O(n) | 线性时间 | 遍历数组 |
O(n log n) | 线性对数时间 | 快速排序、归并排序 |
O(n²) | 平方时间 | 冒泡排序、选择排序 |
O(n³) | 立方时间 | 三重嵌套循环 |
O(2ⁿ) | 指数时间 | 递归求解斐波那契数列 |
O(n!) | 阶乘时间 | 旅行商问题(TSP)暴力解法 |
4. 如何计算时间复杂度?
方法 1:统计基本操作次数
基本操作指的是影响运行时间的核心代码(如循环、递归调用等)。
方法 2:忽略常数项
时间复杂度关注增长趋势,忽略常数。例如:
- O(2n) 简化为 O(n)
- O(3n² + 5n + 10) 简化为 O(n²)
方法 3:只保留最高阶项
例如:O(n² + n) 取最高阶项 O(n²)。
5. 计算示例
示例 1:遍历数组
void loop(int arr[], int n) {for (int i = 0; i < n; i++) { // n 次执行printf("%d", arr[i]); // O(1)}
}
- 时间复杂度:O(n)
示例 2:嵌套循环
void nestedLoop(int n) {for (int i = 0; i < n; i++) { // O(n)for (int j = 0; j < n; j++) { // O(n)printf("%d", i * j); // O(1)}}
}
- 时间复杂度:O(n²)
示例 3:对数复杂度
void logComplexity(int n) {for (int i = 1; i < n; i *= 2) { // i 每次翻倍printf("%d", i);}
}
- 时间复杂度:O(log n)
示例 4:递归复杂度
int fibonacci(int n) {if (n <= 1) return n;return fibonacci(n - 1) + fibonacci(n - 2);
}
- 时间复杂度:O(2ⁿ)
6. 复杂度增长趋势(直观理解)
时间复杂度 | 增长趋势 |
---|---|
O(1) | 超快,固定时间 |
O(log n) | 很快,数据翻倍时时间增加一点 |
O(n) | 线性增长,数据翻倍,时间也翻倍 |
O(n log n) | 接近线性,常见于高效排序 |
O(n²) | 慢,多用于暴力解法 |
O(2ⁿ) | 很慢,指数爆炸 |
O(n!) | 超级慢,几乎无法计算大规模数据 |
7. 总结
- 遍历数组:O(n)
- 嵌套循环:O(n²)
- 二分查找:O(log n)
- 递归斐波那契:O(2ⁿ)
- 高效算法应尽量选择 O(n log n) 或更快的算法! 🚀