剑指 Offer 16. 数值的整数次方

156 阅读1分钟

实现 pow(xn) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。

 

示例 1:

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

示例 2:

输入: x = 2.10000, n = 3
输出: 9.26100

示例 3:

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

 

提示:

  • -100.0 < x < 100.0
  • -231 <= n <= 231-1
  • n 是一个整数
  • 要么 x 不为零,要么 n > 0 。
  • -104 <= xn <= 104

题解

本题,如果使用传统的遍历相乘计算,会超时无法通过。

所以需要换一种思路考虑: 以2^16为例子,我们要求它, 只需要知道2^82^162^8的平方,计算2^8, 只需要知道2^4, 2^82^4的平方,依次类推,原本计算2^16次方需要16次,现在只需要4次即可。

  1. n == 0 时,直接返回 1;
  2. n < 0时, 需要把n转换为正数, 同时x变为1/x;
  3. n > 0时, 分为两种情况,一种是奇数,一种是偶数

通过上面的例子,我们可以推导出用如下公司求xn次方:

xn={xn2xn2,x为偶数xn12xn12x,if x为奇数,x^n = \begin{cases} x^{\frac{n}{2}} * x^{\frac{n}{2}}, & \text x为偶数\\ x^{\frac{n-1}{2}} * x^{\frac{n-1}{2}} * x, & \text{if } x 为奇数, \end{cases}

代码

/**
 * @param {number} x
 * @param {number} n
 * @return {number}
 */
var myPow = function(x, n) {
    return n >= 0 ? quickPow(x, n) : 1 / quickPow(x, -n);

};
/**
 * @param {number} base, 底数
 * @param {number} e, 指数
 * @return {number}
 */
function quickPow(base, e) {
    let res = 1;
    let x = base;
    while(e > 0) {
        // 奇数, 要多乘一个base
        if (e & 1 == 1) {
            res *= x;
        }
        // 偶数,翻倍乘
        x *= x;    

        // 指数减半
        e = Math.floor(e / 2);
    }
    return res;
}

原题链接

剑指 Offer 16. 数值的整数次方