分治算法-Pow(x, n)

369 阅读2分钟

今天在刷题的时候看到一个以前做过的题,但是并没有通过测试,今天把它拿出来重新的做下。 这个题是通过代码实现一个类似Java中Math.pow()这个方法的功能。

那我们就来看下这个题,下面我通过比较暴力的方式和使用分治思想来解决这道题

题目描述

实现 pow(xn) ,即计算 x 的 n 次幂函数(即,xnx^n )。

示例:

输入: x = 2.00000, n = 10
输出: 1024.00000

示例:

输入: x = 2.00000, n = -2
输出: 0.25000
解释: 2^-2 = 1/2^2 = 1/4 = 0.25

提示:

  • -100.0 < x < 100.0
  • -2^31 <= n <= 2^31-1
  • -10^4 <= x^n <+ 10^4

暴力的方式

这里所说的暴力的方式,就是通过循环来解这道题,在循环的时将x乘起来。 因为这里所说的这种解法的时间复杂度是O(n),这并不是一种最优的解法,这里了解下就好,如果想通过这种方法写,自已可以试下。

double result = 1.0;
for i -> n - 1:
    result *= x;
return result;

这里只是写了下伪代码。这种写法比较简单,我就不把代码贴出来了。就是通过循环将x乘起来。但是写的时候要注意示例中还有n < 0的情况。

通过分治+递归的方式

在此之前如果不清楚分治的话可以去网上找相关的文章或者视频。

现在有一个例子:pow(2,10),如何能尽量减少相乘次数的情况下快速的计算出答案呢?

那就要使用到了分治,我们可以将一个大问题分成若干个小问题。

在此之前先回忆下中学学过的一个数学公式:am+n=amana^{m+n}=a^m * a^n

这样说的话:那由上面公式可以得出,我可以先计算出252^5的结果,然后让它的结果相乘这样不就得出了2102^{10}的结果了嘛,因为25+5=25252^{5+5} = 2^5 * 2^5。那么样只需x相乘5次就可以得到了结果(这里的x指的是例子中的2)

话又说回来,那252^5这个是怎么算呢?

这里要注意:在计算2102^{10}我是将指数除了一个2,然后又将252^5的结果相乘才得到的2102^{10}的结果。这是在处理偶数时的方式。

那如果指数是一个奇数怎么处理呢?

这里可以通过取模运算来判断是不是一个奇数,如果是一个奇数的话,我们可以再单独的乘一个x即可。

public static double myPow(double x, long n) {
        long N = n;
        if(n < 0 ) {
           x = 1 / x;
        }
         return f(x,Math.abs(N));
}

public static double f(double x, long n) {
        // base case
        if(n == 0) {return 1;}

        //如果这里结果是1那就需要再乘一个x,如果是0则不需要乘x
        int isMultiplyX = (int) (n % 2);
        double result = 0.0;
        double subResult = f(x,n / 2);
        if(isMultiplyX == 1) {
             result = subResult*subResult*x;
        }else {
             result = subResult*subResult;
        }
        return result;
}

还有在上面示例中要注意一个指数为负数的情况

这种的处理方式就是先将指数转成正数(这里还要注意底数),然后在进行和指数为正数时一样的操作即可。