c - 为什么这段代码的时间复杂度是 O(n) 而不是 O(n^2)?
问题描述
为什么这里的时间复杂度不是 O(n^2) 而是 O(n)?不是第一个循环是n
次,第二个也是一样,所以它变成O(n*n)
了,这里有什么问题?
void f(int n){
for( ; n>0; n/=2){
int i;
for(i=0; i<n; i++){
printf("hey");
}
}
}
解决方案
不是第一个循环是
n
次,第二个循环也是如此,所以它变成了O(n*n)
.
上面的陈述是错误的,因为:
- 外循环不运行
n
时间。(外循环运行O(log n)
时间,但在这种情况下无关紧要。) - 对于内部循环,循环的数量随着值的
n
变化而不同。
为了得到这段代码的时间复杂度,我们应该计算内循环体被执行的总次数。
n
显然,对于每个 的值,内部循环的主体都被执行了几次n
。- 的值
n
由for
外循环的语句决定。它从作为函数参数给出的值开始,每次执行外循环体时减半。
正如评论中已经说明的那样,因为n + n/2 + n/4 + n/8 + ... = 2n
,该算法的时间复杂度是O(n)
。
对于一些更具体的数学证明:
找到一个整数k
,使得2^(k-1) < n <= 2^k
。为此k
:
- 内循环总数的下限是
1 + 2 + 4 + ... + 2^(k-1) = 2^k - 1 >= n - 1 ∈ Ω(n)
。 - 内循环总数的上限是
1 + 2 + 4 + ... + 2^k = 2^(k+1) - 1 < 4n - 1 ∈ O(n)
。
因此,内部循环的总数是Θ(n)
,以及O(n)
。
推荐阅读
- python - 如何在 Django Rest Framework API 视图中隐藏密码字段的值
- python - Django 创建定期付款
- r - 如何在 R 中制作二维数据帧数组?(每个单元格都是一个数据框)
- python-3.x - Python 匹配文件中的所有 URL,并在文件中的新行上列出每个 URL
- c# - IQueryable where 子句检查动态数组
- java - 不得附加 ViewHolder 视图
- javascript - 如何使用 Puppeteer 捕获页面中的所有链接?
- javascript - 如何将状态从页面传递到组件并返回到页面?
- python-3.x - 如何使用 MultiIndex 在 Python 数据框列中进行字符串替换
- javascript - 检查鼠标是否在元素 A 或元素 B 上