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

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

其实就是要求实现pow() 函数 这里蛮力法是通不过的
未通过的测试样例

2.00000
-2147483648

蛮力法时间复杂度为O(n) 因此需要O(nlogn)级别的算法

//蛮力法
class Solution {
public:
    double myPow(double x, int n) {
        if(x==1||n==0) return 1;
        if(n<0) {x=1.0/ x;n=-n;}
        double res=x;
        for(long i=1;i<n;i++)
        {
            res=res*x;
        }
        return res;
    }
};

这里首当其冲的就是二分快速幂运算
譬如当我们计算 2^10 可以分解为 两个2^5相乘
而2^5 又可以分解为两个2^2相乘再乘一个2
就可以极大缩减计算量

同时需要注意一个小坑:
因为我们计算负次幂时 利用 x^(-y)= (1/x)^y
所以存在n由负转正,但题目说n 是 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1]
转正有可能溢出,所以需要借助long型作为辅助

这里是递归二分运算代码
注意我标注的地方:不能写成getres(x,mid)乘getres(x,mid)
否则相当于两次递归 还是O(N)级别

class Solution {
public:
    double getres(double x,long N)
    {
        if(N==1) return x;
        long mid=N/2;
        if(N%2==0) 
        {
            double half=getres(x,mid); //不能写成getres(x,mid)*getres(x,mid);
            return half*half;
        }
        else
        {
            double half=getres(x,mid);
            return x*half*half;
        }
    }
    double myPow(double x, int n) {
        if(x==1||n==0) return 1;
        long N=n;
        if(N<0) return getres(1.0/ x, -N);
         return getres(x,N);
    }
};

也可以进一步思考
譬如当我们计算 2^10
10的二进制是1010 所以我们可以分解为 2的2^1乘 2的 2^3
也就是说2^10 =4乘256=1024
当二进制位为1时 res*=x;
每次执行 x*=x,二进制右移一位

class Solution {
public:
    double myPow(double x, int n) {
        if(x == 1 || n == 0) return 1;
        double ans = 1;
        long num = n;
        if(n < 0){
            num = -num;
            x = 1/x;
        }
        while(num){
            if(num & 1) ans *= x;
            x *= x;
            num >>= 1;
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值