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/22 = 1/4 = 0.25

说明:

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

解法一:

//时间复杂度O(n), 空间复杂度O(1)
class Solution {
public:
    double myPow(double x, int n) {
        if(x == 1.0) return 1.0;
        if(x == 0.0 && n != 0) return 0.0;
        if(n == 0) return 1.0;
        
        long n2 = n;
        if(n2 < 0) {
            x = 1 / x;
            n2 = -n2;
        }
        
        double res = x;
        long cnt = 1;
        while(cnt < n2) {
            if(cnt <= n2 / 2) {//节省时间
                res *= res;
                cnt *= 2;
            }
            else {
                res *= x;
                cnt++;
            }
        }
        return res;
    }
};

解法二:

//时间复杂度O(logn), 空间复杂度O(1)
class Solution {
public:
    double myPow(double x, int n) {
        long n2 = n;
        if(n2 < 0) {
            x = 1 / x;
            n2 = -n2;
        }
        
        double res = 1;
        double curPdt = x;
        while(n2 > 0) {
            if(n2 % 2 == 1) res *= curPdt;
            curPdt *= curPdt;
            n2 /= 2;
        }
        return res;
    }
};

解法一:

是暴力法的改版,使用res作为中间累乘的结果,循环里的每一步都将res自乘以x的某次幂。如果当前累乘次数cnt的2倍不大于n时,说明可以将res直接变为其平方,cnt计数直接变为2倍;否则就只乘x的1次幂,cnt++。最恶劣的情况,需要进行n/2次也就是线性时间。

解法二:

是解法一的改版,使用了额外的一个变量curPdt代表当前幂,curPdt初始为x,自平方增长。此解法将n以二进制位的形式来看,如果其最低位为1,说明res要自乘以curPdt;否则只需要增长curPdt即可。

总体的效果就是,要找出一个x的幂的序列,该序列的和刚好为n,且序列的元素个数最小。

        //核心代码
        while(n2 > 0) {
            if(n2 % 2 == 1) res *= curPdt;//如果位为1,需要乘入res
            curPdt *= curPdt;//curPdt继续自平方增长
            n2 /= 2;//n2右移位
        }

例如输入为(2,18),18的二进制表示为 0001 0010b,看位为1的位就容易知道,18可拆分为 2 加 16:0001 0000b + 0000 0010b,也就是pow(2, 18) = 2^18 = 2^2 * 2^16 = 4294967296。

以下是代码的运行步骤:

        循环次数    res     curPdt      curPdt中x的幂次              n2
        0           1       x=2              1                  18(0)
        1           1       4                2                  9(1)
        2           4       16               4                  4(0)
        3           4       256              8                  2(0)
        4           4       65536            16                 1(1)
        5           262144  4294967296       32                 0(终止)

以上乘入res的x的幂次为:2,16。

2019/10/09 13:37
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值