(LeetCode 50) Pow(x, n) [递归 & 非递归 & 对非指数的处理]

50. Pow(x, n)

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

示例 1:

输入: 2.00000, 10
输出: 1024.00000
示例 2:

输入: 2.10000, 3
输出: 9.26100
示例 3:

输入: 2.00000, -2
输出: 0.25000
解释: 2^-2 = (1/2)^2 = 1/4 = 0.25
说明:

-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1] 。

分析:
(1)对于负指数情况的处理:
我们希望对于负指数情况的处理,可以像正指数情况那样,采用一样方法进行处理。

对于 pow(3, -7)的情况,我们可以将其转换为 pow(1/3, 7),即我们将指数 -n 中的负号,移动到 x 上 , 将 x 转换为 x ^ -1 。这样,对于负指数情况的处理,可以像正指数情况那样,采用一样方法进行处理。

(2)关于负数转换为正数,范围越界的处理
关于(1)中对于负指数情况的处理,会存在边界问题,即int范围中,负数比正数多一个数。若将 -n 直接变成 n ,在 -n 为 −2^31 时, n 为 2^31,超出了int的范围。

令 n’ = n+1 = -2147483647 。求x^n等价于求 x^n’ * x-1

即我们先拿出一个 1/x 出来,然后再尽心符号的变换,这样就可以避免越界的情况出现了。

(3)递归思想:
递归思想非常的简单,
当 n 为偶数时, 先递归求出指数为一半的值, half = myPow(x, n >> 1); 返回 half *= half; 计算后的half 即可,
当n 为奇数时,先递归求出指数为一半的值, half = myPow(x, n >> 1); 返回 half *= half; half *= x; 计算后的half 即可,

递归代码:

class Solution {
public:
   double myPow(double x, int n) {
        if (n < 0)
            return 1 / x * myPow(1 / x, -(n + 1));
        else if (n == 0)
            return 1;
        double half = myPow(x, n >> 1);
        half *= half;

        if ((n & 1) == 1)
            half *= x;
        return half;
    }
};

(4)非递归思想:
任何一个int数,都可以用32为的二进制01表示。
例如: 当我们要求解pow(3, 7)时,7的二进制为111,三个1分别代表1,2,4。所以3^7 可以分解为:3^1 * 3^2 * 3^4 。
因此我们只需要判断 n 的二进制数中哪些位为1,然后分别乘上x的相应指数倍即可。
在循环的过程中,我们一直使用tmp来记录在当前上,x的相应指数倍的值。

非递归代码:

class Solution {
public:
    
   double myPow2(double x, int n)
   {
       double ans = 1.0;
       double tmp = x;
       while(n)
       {
           if((n & 1))
           {
               ans *= tmp;
           }
           tmp *= tmp;
           n = n>>1;
       }
       return ans;
   }
    
   double myPow(double x, int n) {
        if (n == 0) return 1;
        else if (n < 0)
            return 1 / x * myPow2(1 / x, -(n + 1));
        else return myPow2(x, n);
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值