【问题标题】:Exponentiation complexity指数复杂度
【发布时间】:2017-08-04 21:07:16
【问题描述】:

基于此代码:

int poow(int x,int y)
{
    if(y==0)
        return 1;

    if(y%2!= 0)
        return poow(x,y-1)*x;

    return poow(x,y/2)*poow(x,y/2); //this line 

}

我试图查看复杂性:我们假设我们有 n=2^k

我们有 T(0)=1

T(n)=2*T(n/2)+C

T(n)=2^i * T(n/2^i)+i*c

对于 i=k,我们有 T(n)=2^k * T(n/2^k) + k * c

T(n)=2^k * T(1) + k*c

T(n)=2^k * c2 + k * c

我被困在这里?如何继续计算复杂性以及更改此行时有什么区别:

return poow(x,y/2)*poow(x,y/2); //this line 

int p=poow(x,y/2);
return p*p;

就复杂性而言!

【问题讨论】:

  • 那么..关于您遇到问题的代码,您有什么问题?
  • 你犯了一个错误。 T(n)=2*T(n/2)+C = T(n)=2*(2*T(n/4) + C)+C = 4*T(n/4) + 3C != 4*T(n/4) + 2C
  • 这个错误其实并不重要,但还是谢谢。
  • 第一个是O(n),第二个是O(lg n)。我认为这很简单,哪个更好:)
  • x*pow(x,n-1) 可能比pow(x,n-1)*x更快(但可能不是),但复杂性与速度无关,而与缩放。两者具有相同的复杂性。

标签: c algorithm time-complexity analysis


【解决方案1】:

从适当的重复开始。复杂度仅基于y,因此我们可以将递归写为

T(0) = 1

T(y) = y is even:     2 * T(y / 2)
       y is odd:      T(y - 1) + 1

最坏的情况是每除以 2 都会给我们留下一个奇数,这将导致复杂性

T(2^n-1) = 1 + 2 * (1 + 2 * (1 + 2 * ( ... * T(1)))) =
         = 2 ^ 0 + 2 ^ 1 + 2 ^ 2 + 2 ^ 3 + ... + 2 ^ (n - 1) + 2 ^ (n - 1) = 
         = 2 ^ n - 1 + 2 ^(n - 1) = 3 * 2 ^ (n - 1) - 1

T(y) = O(y)

最好的情况是 2 的幂:

T(2^n) = 2 * 2 * ... * 2 * T(1) = 2 ^ n * (1 + 1) = 2 ^ (n + 1) = 2 * 2 ^ n

T(y) = O(y)

现在如果我们优化整个函数呢?

T'(0) = 1

T'(y) = y is even:   T(y / 2) + 1
        y is odd:    T(y - 1) + 1

最坏的情况:

T'(2^n - 1) = T(2^n - 2) + 1 = T(2^(n - 1) - 1) + 1 + 1 = ... =
            = T(1) + 1 + 1 + 1 + ... =
            = 2 + 1 + 1 + 1 + ... =
            = 1 + ln(2^n) / ln(2) * 2 = 
            = 1 + 2 * n

T'(y) = O(log y)

最佳情况:

T'(2 ^ n) = T(1) + 1 + 1 + ... =
          = 2 + 1 + 1 + ... =
          = 2 + ln(2^n) / ln(2)
          = n + 2

T'(y) = O(log y)

所以优化后的版本肯定更快(线性复杂度 vs 对数复杂度)。

【讨论】:

    【解决方案2】:

    有时代码分析侧重于理论而不是实际。

    代码有错误。

    if(y%2!= 0)
        return poow(x,y-1)*x;
    // should be
    if(y%2!= 0)
        return poow(x,y-y%2)*x;
    
    // better alternative, use 
    unsigned poow(unsigned x, unsigned y) 
    

    如果没有修复,调用 poow(1,-1) 会导致无限递归并可能导致堆栈溢出。所以 O(∞) 不管最后一行是return poow(x,y/2)*poow(x,y/2); 还是int p=poow(x,y/2); return p*p;

    【讨论】:

      猜你喜欢
      • 2014-03-21
      • 1970-01-01
      • 2017-05-27
      • 2019-06-13
      • 1970-01-01
      • 2016-03-03
      • 2017-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多