CPH-第二章 时间复杂度
时间复杂度可以量化算法效率,根据输入规模,在编码前预判算法是否能在时限内通过,并因此进行算法优化。
2.1 时间复杂度计算规则
- 时间复杂度用 \(O(\cdots)\) 表示,以输入规模 \(n\) 为参数,只描述效率的数量级,不关心具体常数。
循环与嵌套循环
- 算法的耗时主要来自循环,嵌套循环的层数决定了复杂度量级:\(k\) 层嵌套循环对应 \(O(n^k)\)。
- 单层循环遍历数组:\(O(n)\)
- 两层嵌套遍历所有元素对:\(O(n^2)\)
数量级
-
复杂度只反映增长趋势,与循环次数的常数系数、起始结束的小偏移无关。
- 循环 \(3*n\) 次、\(n+5\) 次、步长为 2 的循环,均为 \(O(n)\)。
- 只遍历数组上三角的双层循环\(i<j\),仍为 \((n^2)\)。
多阶段取最大值
-
如果算法由多个连续阶段组成,总时间复杂度等于最慢阶段的复杂度,即瓶颈由耗时最长的部分决定。
- 例如三个阶段复杂度分别为 \(O(n)\)、\(O(n^2)\)、\(O(n)\),总复杂度为 \(O(n^2)\)。
多变量复杂度
-
如果算法效率依赖多个输入规模,复杂度公式会包含多个变量。
- 例如遍历 \(n \times m\) 的二维数组,复杂度为 \(O(n*m)\)。
递归的复杂度
-
递归函数的时间复杂度 = 递归调用总次数 × 单次调用的复杂度。
- 单递归(每次调用自身 1 次):例如 \(f(n)\) 调用 \(f(n-1)\),共调用 \(n\) 次,总复杂度 \(O(n)\)。
- 双递归(每次调用自身 2 次):例如 \(g(n)\) 调用两次 \(g(n-1)\),调用总次数为 \(2^n-1\),总复杂度 \(O(2^n)\)。
2.2 常见复杂度等级
- 按效率从高到低排列,可分为多项式与非多项式两大类:
| 复杂度 | 特点与典型场景 |
|---|---|
| \(O(1)\) | 常数时间,不依赖输入规模,通常为直接公式计算 |
| \(O(\log n)\) | 对数级,每步将输入规模减半,如二分查找 |
| \(O(\sqrt{n})\) | 平方根级,慢于对数、快于线性 |
| \(O(n)\) | 线性级,遍历输入常数次,通常是问题的理论最优 |
| \(O(n \log n)\) | 常出现在排序算法,或使用单次操作 \(O(\log n)\) 的数据结构 |
| \(O(n^2)\) | 平方级,两层嵌套循环,遍历所有元素对 |
| \(O(n^3)\) | 立方级,三层嵌套循环,遍历所有元素三元组 |
| \(O(2^n)\) | 指数级,遍历所有子集,非多项式 |
| \(O(n!)\) | 阶乘级,遍历所有排列,非多项式 |
2.3 效率估算方法
基本估算依据
- 现代计算机每秒可执行数亿次操作,结合题目时间限制(通常 1 秒),可以通过输入规模反推所需的算法复杂度。
1 秒时限下的输入规模对应表
| 最大输入规模 | 对应可通过的复杂度 |
|---|---|
| \(n \le 10\) | \(O(n!)\) |
| \(n \le 20\) | \(O(2^n)\) |
| \(n \le 500\) | \(O(n^3)\) |
| \(n \le 5000\) | \(O(n^2)\) |
| \(n \le 10^6\) | \(O(n)\) 或 \(O(n \log n)\) |
| n 极大 | \(O(1)\) 或 \(O(\log n)\) |
注意事项
- 时间复杂度仅为估算,它隐藏了常数因子,实际运行时间会受实现细节影响,但足以快速排除不可行的算法思路。
浙公网安备 33010602011771号