确定代码段的时间复杂度

Posted

技术标签:

【中文标题】确定代码段的时间复杂度【英文标题】:Determining the time complexity for code segments [duplicate] 【发布时间】:2017-09-07 20:53:57 【问题描述】:

以下每个代码段的时间复杂度是多少?

1. int i, j, y=0, s=0;
for ( j = 1; j <= n; j ++) 

  y=y+j;

for ( i = 1; i <= y; i ++) 

  s++;

我的答案是 O(2n),因为它遍历每个循环 n 次并且有两个循环

2. function (n) 
  while (n > 1) 
  n = n/3 ;

我对此的回答是 n^(1/3),因为 n 每次都会变成它的三分之一

3. function (n) 
int i, j, k ;
for ( i = n/2; i <= n; i ++ )    //n/2?
  for ( j = 1; j <= n; j = 2*j )   //logn
    for ( k = 1; k <= n; k = 2*k )   //logn
      cout << ”COSC 2437.201, 301” << endl;
    
  

  

我说这个问题的答案是 O(log2*log2n*n/2) 但我对第一个 for 循环感到很困惑。循环只需要迭代 n 次的一半,所以它是 n/2 正确的吗?谢谢大家的帮助。

【问题讨论】:

首先,O(2n) 只是 O(n) - 这是问题 1 的错误答案。 第一个 for 循环究竟是什么让你感到困惑? 第一段怎么可能是 O(n) 之外的任何东西?对于第一个循环,循环只需要迭代 n 次的一半,所以它会是 n/2 正确吗? 第二个循环呢?这取决于第一个循环后y 的值,对吧?那会是什么? "n^(1/3) 因为 n 每次都变成它的三分之一" 不合逻辑。 【参考方案1】:

问题 1

第一个循环是O(n),因为它运行n 次。 然而,第二个循环执行y 次,而不是n - 所以总运行时间不是“2n

在第一个循环结束时,y 的值为:

因此第二个循环占主导地位,因为它是O(n^2),因此也是整体复杂度。


问题 3

这个答案是正确的(但同样,在 O 表示法中删除 2 的因子)。

但是,您必须小心不要天真地将循环的复杂性相乘,因为内部循环的边界可能取决于外部循环的自发值。


问题 2

不是O(n^(1/3))!你的推理是错误的。

如果仔细观察这个循环,它实际上类似于问题 3 中的内部循环的 reverse

在第三季度,k 的值从 1 开始,每次乘以 2,直到达到 n 在第二季度,n 的值每次除以 3,直到达到 1。

因此他们都采取O(log n) 步骤。

(顺便说一句,O(n^(1/3)) 循环看起来像这样:)

for (int i = 1; i*i*i <= n; i++)
   /* ... */

【讨论】:

帮别人做作业是可以的,但不要为他们 @n.m.你是对的;我认为 OP 可能需要更多的解释,而不是挤进评论中 我的意思是我不只是想得到答案。您的回答是唯一真正帮助我了解发生了什么的答案。谢谢。

以上是关于确定代码段的时间复杂度的主要内容,如果未能解决你的问题,请参考以下文章

复杂段的路由问题

数据结构1(概述)

如何确定这段代码的时间复杂度?

数据结构时间复杂度讲解和练习

Swift 中的复杂导航栈

两个嵌套for循环的时间复杂度