【Getting Started】-时间复杂度-Time Complexity
文章目录
- 时间复杂度计算-Complexity Calculations
- 常见的复杂度和限制-Common Complexities and Constraints
- 问题集-Quiz
计算算法执行的操作次数。
Measuring the number of operations an algorithm performs.
在编程竞赛中,程序需要在限定时间内运行才能获得评分。例如,对于 USACO,C++ 提交的时间限制是 2 2 2 秒,Java/Python 提交的时间限制是 4 4 4 秒。对评分服务器每秒能处理的操作数量的保守估计是 1 0 8 10^8 108,但如果常数因子较好,实际值可能接近 5 ∗ 1 0 8 5*10^8 5∗108
资料-resources
-
3 - Algorithm Analysis
-
2 - Time Complexity
-
5 - Time Complexity
时间复杂度计算-Complexity Calculations
我们需要一种方法来计算运行每个算法所需的操作次数,这个次数是输入大小 n n n 的函数。
幸运的是,这可以通过大 O O O 表示法轻松完成,它将最坏情况下的时间复杂度表示为输入大小 n n n 的函数,并且随着 n n n 趋向无穷大。复杂度是算法所需步骤的上界。
使用大 O O O 表示法,我们将一个函数的复杂度表示为 O ( f ( n ) ) O(f(n)) O(f(n)),其中常数因子和低阶项通常被省略。
以下代码的时间复杂度为 O ( 1 ) O(1) O(1),因为它执行的操作数是固定的。
int a = 5;
int b = 7;
int c = 4;
int d = a + b + c + 153;
输入和输出操作也被假定为 O ( 1 ) O(1) O(1)。在以下示例中,我们假设循环内的代码是 O ( 1 ) O(1) O(1)。
循环的时间复杂度取决于循环的迭代次数。例如,以下代码示例的时间复杂度都是 O ( n ) O(n) O(n)。
for (int i = 1; i <= n; i++) {
// constant time code here
}
int i = 0;
while (i < n) {
// constant time code here
i++;
}
计算时间复杂度,通常忽视常数因子阶和低阶项,所以以下代码的时间复杂度也为 O ( n ) O(n) O(n)
for (int i = 1; i <= 5 * n + 17; i++) {
// constant time code here
}
for (int i = 1; i <= n + 457737; i++) {
// constant time code here
}
通过将每个循环的时间复杂度相乘来找到多个循环的时间复杂度,以下代码的时间复杂度为 O ( n ∗ m ) O(n*m) O(n∗m)
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
// constant time code here
}
}
一个算法包含多个块,时间复杂度为所有块中最差的时间复杂度,以下代码的时间复杂度为 O ( n 2 ) O(n^2) O(n2)
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// constant time code here
}
}
for (int i = 1; i <= n + 58834; i++) {
// more constant time code here
}
以下代码的时间复杂度为 O ( n 2 + m ) O(n^2+m) O(n2+m)【彼此都不互为低阶项】
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// constant time code here
}
}
for (int i = 1; i <= m; i++) {
// more constant time code here
}
常见的复杂度和限制-Common Complexities and Constraints
- 计算答案的数学公式 - O ( 1 ) O(1) O(1)
- 二分查找 - O ( l o g n ) O(logn) O(logn)
- Sorted set/map/priority - O ( l o g n ) O(logn) O(logn)
- 整数进行质因数分解、检查是否为素数 - O ( n ) O(\sqrt{n}) O(n)
- 快速、归并排序 - O ( n ∗ l o g n ) O(n*logn) O(n∗logn)
- 读入/遍历数组 - O ( n ) O(n) O(n)
- 迭代所有大小为 k 的子集 - O ( n k ) O(n^k) O(nk)
- 迭代所有的子集 - O ( 2 n ) O(2^n) O(2n)
- 全排列 - O ( n ! ) O(n!) O(n!)
n | 时间复杂度 |
---|---|
n ≤ 10 n \leq 10 n≤10 | O ( n ! ) 、 O ( n 7 ) 、 O ( n 6 ) O(n!)、O(n^7)、O(n^6) O(n!)、O(n7)、O(n6) |
n ≤ 20 n \leq 20 n≤20 | O ( 2 n ∗ n ) 、 O ( n 5 ) O(2^n * n)、O(n^5) O(2n∗n)、O(n5) |
n ≤ 80 n \leq 80 n≤80 | O ( n 4 ) O(n^4) O(n4) |
n ≤ 400 n \leq 400 n≤400 | O ( n 3 ) O(n^3) O(n3) |
n ≤ 7500 n \leq 7500 n≤7500 | O ( n 2 ) O(n^2) O(n2) |
n ≤ 7 ∗ 1 0 4 n \leq 7*10^4 n≤7∗104 | O ( n n ) O(n \sqrt{n}) O(nn) |
n ≤ 5 ∗ 1 0 5 n \leq 5 * 10^5 n≤5∗105 | O ( n l o g n ) O(nlogn) O(nlogn) |
n ≤ 5 ∗ 1 0 6 n \leq 5*10^6 n≤5∗106 | O ( n ) O(n) O(n) |
n ≤ 1 0 18 n \leq 10^{18} n≤1018 | O ( l o g 2 n ) 、 O ( l o g n ) 、 O ( 1 ) O(log^2n)、O(logn)、O(1) O(log2n)、O(logn)、O(1) |
问题集-Quiz
1、什么是时间复杂度?
A、测量算法消耗的内存量
B、测量算法执行的操作数量
C、解决问题所需的时间
Answer:B,你总是希望你的算法运行得尽可能快!
2、大 O 符号表示什么?
A、最好的情况
B、最坏的情况
C、平均情况
Answer:B