通过平方时间复杂度来取幂

时间:2013-08-15 09:44:12

标签: c++ c algorithm big-o

我不明白如何通过对O(log n)乘法求平方来进行取幂。

在我看来,你最终做的不仅仅是log n乘法(其中n是指数的大小)。

示例:

              power(2,8)
       /                       \
     pow(2,4)        *          pow(2,4)
    /        \                 /        \      
pow(2,2) * pow(2,2)          pow(2,2) * pow(2,2)
   /               \             /              \
 p(2,1)*p(2,1) p(2,1)*p(2,1)  p(2,1)*p(2,1)    p(2,1)*p(2,1)

这是七次乘法,就像常规取幂一样。

以下是我尝试过的3种方法:

long pow(int base, int exp)
{
  if(exp == 1)
    return base;
  else
    return base * pow(base, exp-1);
}

long pow2(int base, int exp)
{
  if(exp == 1)
    return base;
  else if(exp == 0)
    return 1;
  else
    if(exp % 2 == 0)
      return pow2(base * base, exp/2);
    else
      return base * pow2(base * base, exp/2) ;
}

long pow3(int base, int exp)
{
    if(exp == 1)
        return base;
    int x = pow2(base,exp/2);
        if(exp%2 == 0)
            return x*x;
        else
            return base*x*x;
}

似乎一旦递归到底,就会执行相同数量的乘法......

3 个答案:

答案 0 :(得分:3)

您应该只考虑一个分支,因为您保存结果并且不重新计算分支。实际上只完成了以下乘法运算:

              power(2,8)
       /                       \
     pow(2,4)        [*]        pow(2,4)
    /        \                 /        \      
pow(2,2) [*] pow(2,2)        pow(2,2) * pow(2,2)
   /               \             /              \
 p(2,1)[*]p(2,1) p(2,1)*p(2,1)  p(2,1)*p(2,1)    p(2,1)*p(2,1)

答案 1 :(得分:2)

你正在显示一个二叉树,但你的递归函数不会自己调用两次,只调用一次,所以它只遍历一个logN路径。

此外,此算法的递归是愚蠢的(缓慢,复杂,脆弱)。 只需遍历指数位:

long pow(long base, int exp) {
    long result = 1;
    while (exp > 0) {
        if (exp & 1) result *= base;
        exp >>= 1;
        base *= base;
    }
    return result;
}

答案 2 :(得分:1)

让我们来看看你的考试2 ^ 8。在第一步,你必须计算2 ^ 4。当你得到结果时,只需将其自身相乘。您不必计算整个树,因为您已经知道结果。我们来看看你的示例树。在这种情况下,您只需要计算最左侧的树。这意味着只有2 ^ 4,2 ^ 2,2 ^ 1然后使用结果得到2 ^ 8。

此外,您的功能应该是这样的:

int power(int base, int power) {
    if (power == 0)
        return 1;
    if (power == 1)
        return base;
    int result = power(base, power / 2);
    result *= result;
    if (power % 2 == 1)
         result *= base;
    return result;
}