uacs2024

导航

leetcode 50. Pow(x, n) 中等

50. Pow(x, n)

要特别注意 n 的范围 ,如果 n = -2^31,使用int 是不可以直接 n = -n; 的

一、使用long

这里做的时候没注意到已经使用了pow,所以这题可以说使用long做出来

class Solution {
public:
    double myPow(double x, int n) {
        if(x == 0)  return 0;
        if(n == 0)  return 1;
        if(n == 1)  return x;
        if(x == 1)  return 1;
        long nTemp = n;
        if(nTemp < 0){
            x = 1.0/x;
            nTemp = -nTemp;
        }

        double res = 1.0;
        long count = 0;
        vector<double> mult;
        mult.push_back(x);
        //比如n = 35,那么两两平方的次数为log(35)向下取整
        //x^1  x^2  x^4  x^8  x^16  x^32   最多平方5次

        int log2 = (int)(log(nTemp)/log(2));
        for(int i = 0;i < log2;i++){
            double t = mult.back();
            mult.push_back(t*t);
        }
       
        int size = mult.size();
        for(int i = size-1;i >= 0;i--){
            if(count + pow(2,i) <= nTemp){
                res *= mult[i];
                count += pow(2,i); //count代表目前res=x^count
                //没留意到这里已经使用了pow,属于违反条件了
            }
        }
        return res;

    }
};

 

二、不使用long

不使用long就要对边界条件单防了。

class Solution {
public:
    //单独计算小范围的2^n
    int pow2(int n){
        if(n == 0)  return 1;
        int res = 1;
        while(n > 0){
            res *= 2;
            n--;
        }
        return res;
    }
    
    double myPow(double x, int n) {
        if(x == 0)  return 0;
        if(n == 0)  return 1;
        if(n == 1)  return x;
        if(x == 1)  return 1;
        if(x == -1){
            if(n == INT_MIN)  return 1;
            if(n < 0)  n = -n;
            if(n%2==0)  return 1;
            else  return -1;
        }
        if(n == INT_MIN){
            if(abs(x)>1)  return 0;
            return (1.0/x)*myPow(1.0,INT_MAX);
        }

        if(n < 0){
            x = 1.0/x;
            n = -n;
        }

        double res = 1.0;
        int count = 0;
        vector<double> mult;
        mult.push_back(x);

        int log2 = (int)(log(n)/log(2));
        for(int i = 0;i < log2;i++){
            double t = mult.back();
            mult.push_back(t*t);
        }
       
        int size = mult.size();
        for(int i = size-1;i >= 0;i--){
            if(count + pow2(i) <= n){
                res *= mult[i];
                count += pow2(i);
            }
        }
        return res;

    }
};

 我的这种用vector来保存2^k次方的做法对内存消耗还是很大的

题解

一、快速幂 + 递归

class Solution {
public:
    double quickMult(double x,long n){
        if(n == 0)  return 1;
        double y = quickMult(x,n/2);
        if(n % 2 == 0)  return y*y;
        else  return y*y*x;
    }

    double myPow(double x, int n){
        long N = n;
        return N > 0 ? quickMult(x,N) :quickMult(1.0/x,-N);
    }
};

 

二、快速幂 + 迭代

我原本的做法跟这个有点类似,我使用vector本质就是想把这里说的有贡献的2^k次方保存起来

这个方法的关键就是 , 根据 n 的二进制 ,1 的位置所代表的次方就是有贡献的

class Solution {
public:
    double quickMult(double x,long n){
        if(n == 0)  return 1;
        if(x == 1)  return 1;
        if(x == 0)  return 0;
        double res = 1.0;
        double x_contribute = x;
        while(n > 0){
            if(n % 2 == 1)  res *= x_contribute;
            x_contribute *= x_contribute;
            n /= 2;
        }
        return res;
    }

    double myPow(double x, int n){
        long N = n;
        return N > 0 ? quickMult(x,N) :quickMult(1.0/x,-N);
    }
};

 

posted on 2024-11-12 21:13  ᶜʸᵃⁿ  阅读(0)  评论(0编辑  收藏  举报