LeetCode | Pow(x, n)


实现double Pow(double x,int n)—-x的n次幂!


题目解析:

这道题目看起来很简单,笨方法,可以一次一次的去乘,也可以折半相乘!看似简单,但中间碰到了不小的问题。

在运行过程中,出现了-2147483648超时。为什么?

来看下面代码:

class Solution{
public:
    double pow(double x,int n){
        if(n == 0)
            return 1.0;
        if(n == 1)
            return x;
        if(n < 0){
            //方案一
            return 1.0/pow(x,-n);
            //方案二
            n = -n;
            double half = pow(x,n/2); //只计算一次,效率更高!
            if(n%2 == 0)
                return 1.0/(half*half);
            return 1.0/(x*half*half);
        }
        double half = pow(x,n/2); //只计算一次,效率更高!
        if(n%2 == 0)
            return half*half;
        return x*half*half;
    }
};

方案一时会报错,但方案二却没有?

差别在哪里?在于整数正负数范围不对称引起的错误,-2147483648再取负数,还是其自身,那么方案一就会无限死循环下去,深层次的n还是小于0。但方案二却没有,因为传递的时候已经确保了n/2不再是最大的负数,会跳出死循环。


网上还有另外一种方法,也没有出错,来看一下:

class Solution {
public:
    double powPositive(double x, int n){
        if(n == 0) return 1;
        if(n == 1) return x;
         
        double tmp;
        if(n%2 == 0){
            tmp = powPositive(x, n/2);
            return tmp*tmp;
        }
         
        tmp = powPositive(x, n/2);
         
        return tmp*tmp*x;
    }
     
    double pow(double x, int n) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(n >= 0) return powPositive(x,n);
        return 1/powPositive(x,-n);
         
    }
};

他也是直接将-n传入。但不是本身的函数,而是子函数,况且子函数当中也不再对负数n进行判断。最后能通过测试。


但更完美的方法还是《【剑指offer】面试题11:数值的整数次方》这个里面的方案,已经把0的情况也考虑进去了,并且对负数进行了的彻底的转化unsigned int ,同时调用子函数去求解。

这道题还是很值得仔细去研究的。


点赞