使用递归的分而治之算法计算整数幂

时间:2014-08-12 15:31:02

标签: java recursion

我已经实现了一个递归函数来找到m ^ n(m被提升到幂n)。

现在我想实现相同的功能,但是将问题分成两个相等的部分,比如

m^n = m^(n/2) * m^(n/2) = ...(即使是n,m ^ 2,m ^ 4,m ^ 6)。

通过下面的实现,如果我给m = 2和n = 4,我的输出 4 ,而它应该 16

public class Recursion {

  public static void main(String[] args) {
    System.out.println(pow(2, 4));
  }

  public static long pow(long m,long n) { 
    if (n > 0)
      return m * pow(m, ((n/2) - 1) * pow(m, ((n/2) - 1)));
    else
      return 1;
  }

}

5 个答案:

答案 0 :(得分:4)

public static long pow(long m,long n)
{ 
    if (n <= 0) {
        return 1; // Be lazy first
    } else if (n % 2 == 1) {
        return m * pow(m, n - 1); // Normal slow strategy
    } else { // n even
        long root = pow(m, n / 2); // Do not evaluate twice
        return root * root;
    }
}

答案 1 :(得分:2)

基于这里的两个其他答案的组合,我相信这是最佳算法:

public static long pow(long m, int n)
{ 
    if (n <= 0) {
        return 1;
    } else if (n == 1) {
        return m;
    }

    int rem = n & 1;
    n >>= 1;

    if (rem == 0) {
        return pow(m * m, n);      // x^(2n) = (x^2)^n 
    } else {
        return m * pow(m * m, n);  // x^(2n+1) = x * ((x^2)^n)
    }
}

即。 m ^ 0或m ^ 1的立即短路,以及其他情况的单个递归调用。

编辑稍微清理一下,现在正好遵循exponentiation by squaring上的维基百科文章,该文章在算法上与我之前的编辑相同,但现在通过偶数情况可能尾部递归得到改善支持它的语言。

答案 2 :(得分:1)

此答案会在无效输入上添加错误报告并处理所有极端情况:

public long pow(long base, long exponent) {
    if (exponent < 0) {
        if (base == 1) {
            return 1;
        } else if (base == -1) {
            return exponent % 2 == 0 ? 1 : -1;
        } else {
            throw new ArithmeticException("Negative exponent");
        }
    } else if (exponent == 0) {
        if (base == 0) {
            throw new ArithmeticException("0**0 is undefined");
        } else {
            return 1;
        }
    } else {
        long root = pow(base, exponent/2);
        long result = root * root;
        if (exponent % 2 != 0) {
            result *= base;
        }
        return result;
    }
}

从技术上讲,这会计算截断的结果以适合long。要检测溢出,乘法应替换为this

对于非递归解决方案,用

替换最后的else块
long result = 1;
while (exponent != 0) {
    if (exponent % 2 != 0) {
        result *= base;
    }
    base *= base;
    exponent /= 2;
}
return result;

答案 3 :(得分:0)

试试这个,它根据需要分成两部分进行计算。另请参阅http://en.wikipedia.org/wiki/Exponentiation_by_squaring了解其他方法

class Main {

    public static void main(String[] args) {    
        System.out.println(pow(2, 4));    
    }

    public static long pow(long m, long n) {
        if (n > 1)
            return pow(m, (n / 2)) * pow(m, (n - (n / 2)));
        else if (n <= 0)
            return 1;
        else
            return m;
    }
}

答案 4 :(得分:0)

如果你将m加起来

1+n/2-1+n/2-1

减少到

n - 1

另外,你错放了一些括号,所以你实际上并没有在你想象的地方成倍增加。您将乘以pow((n/2) -1) to the partial n in your first pow`电话的结果。