【问题标题】:how to calculate time complexity of for (int i = n - 1; i != 0; i /= 2) ?如何计算 for (int i = n - 1; i != 0; i /= 2) 的时间复杂度?
【发布时间】:2013-09-17 03:36:41
【问题描述】:

for (int i = n - 1; i != 0; i /= 2) ++k;

我无法理解如何计算上述时间复杂度。当 n 为负时,我无法弄清楚它的行为。谁能帮我到那里。当 n 为正时,我尝试过。

Statement            Code      Time 
1a                  i=n-1       1 
1b                  i != 0    log2n+1
1c                  i = i/2   log2n
2                    ++k      log 2n
Total running time       3 log 2n+2

当我分析 n 为正的代码时,我得到了这些值。但是当 n 为负数时我没能得到

【问题讨论】:

  • 你是如何达到你目前的价值观的?您的分析中似乎缺少一些步骤。
  • 两者都是一样的:O(log n)
  • 当n为正或负时,为logn(以2为底)。
  • 如果 n 是 2 的 16 次幂,那么它将循环大约 16 次,而不是 2 的 16 次幂。
  • 另外,对数的底数也无所谓,因为changing the base只做一个常数因子的差值,而big-oh没有考虑常数因子。

标签: algorithm time-complexity


【解决方案1】:

这个算法属于O(log(n))。当abs(n - 1) 是2 的幂时,运行时间最长,因为在所有其他情况下,某些i /= 2 步骤将导致i 取一个值(其绝对值)略小于abs(i / 2),由于截断。

n - 1是2的幂,所以n - 1 == 2**a对于一些a,然后循环将被执行a + 1次(一次对于i取每个值1 = 2**0,@987654331 @、4 = 2**2、……、n - 1 = 2**a)。即循环会被执行 lg(n - 1) + 1 次。

我认为您的一些困惑源于您试图解释循环内执行了多少步,但请记住,这些常数因素对于渐近运行时无关紧要。为了证明运行时间是(比如说)O(log(n)),您只需要证明“n 的实际运行时间”/ log(n)的限制,当 n 接近无穷大时,小于无穷大。如果循环的每次迭代都需要三步或四步,或者一千步,谁在乎呢?只要实际运行时和 log(n) 之间的差距由 some 有限常数从上面限制,那么它就没有区别。出于同样的原因,您无需担心对数的底数(2,或 10,或 e,它只是一个常数因子),甚至循环是否执行 lg(n - 1) 次或 lg(对于任何常数 m 和 p,n - 1 +(-) m) +(-) p 次。

【讨论】:

  • 我很高兴你的解释@Aaron。但是 O(f(n)) 是表达时间复杂度的唯一方法吗?我们可以像我在问题中所做的那样,而不是用某个函数的顺序来表示时间复杂度,而是用某个函数来表示时间复杂度。即 t(n)=3 log 2n+2。如果是,上述问题的时间复杂度是多少。因为,我只是这个算法概念的初学者,如果我的问题合适的话,对不起..
  • 算法的复杂性几乎总是根据约束和/或支配函数来讨论,其中常数因子和常数项不被强调。在这种特殊情况下,不同架构和编译器之间的精确操作数会有所不同,甚至在同一编译器上的选项之间也会有所不同。代码的上下文也可以发挥作用。常数因素有时是一个重要的实际考虑因素,但归根结底,当软件开发人员需要知道某些代码的绝对速度时,他们会使用分析器,而不是操作计数。
猜你喜欢
  • 2021-06-09
  • 1970-01-01
  • 2017-01-12
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2014-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多