50. Pow(x, n)

https://leetcode-cn.com/problems/powx-n/submissions/

  • 把x的n次方用x的n/2次方与x的n/2次方相乘优化,这是一个递归的问题。leetcode把他归在了二分的tag里,所以能用除以二来优化的都算二分
  • x4=x2*x2;x5=x2*x2*x n为奇数和偶数分开进行下一轮递归
  • 递归的结束条件:n一直除以二最终会除到0,n==0返回1。理论上加上n==1直接返回x可以减少一次递归调用,但是leetcode的结果显示并没有优化

 

第一次错的答案

  题目里n有正有负,惯性思维让我把n大于零和n小于零分开讨论。理论上遇到负数要先转成正数计算出结果后在取个倒数,这样会造成溢出的问题,因为有符号数正负区间不对称,负数的范围比正数大一,如果对负数去相反数可能会溢出。

  从递归的角度考虑也不要在递归计算doPow前对正负分开讨论。这是一个递归,考虑递归从底向上考虑,比如x的一次方,doPow(x,1)=doPow(x,0)*doPow(x,0)*x,等于x。而x的-1次方,doPow(x,-1)=doPow(x,0)*doPow(x,0),*,也等于x。所以在递归中正负最终的结果是一样的,本质上因为1除以2等于-1除以2,都等于0。所以正数和负数递归的最底下是相同的,而在递归的过程中也不需要考虑n的正负,故在doPow前不需要对n的正负进行讨论。

public class pow_50 {
    public double myPow(double x, int n) {

        if (n>0){
            return doPow(x,n);
        }else if (n<0){
            return 1/doPow(x,-n);
        }else {
            return 1;
        }
        
    }

    public double doPow(double x,int n){
        if (n==0){
            return 1;
        }
        if (n%2==1){
            double half = doPow(x, n / 2);
            return half * half*x;
        }else {
            double half = doPow(x, n / 2);
            return half*half;
        }
    }

}

正确答案

class Solution {
    public double myPow(double x, int n) {
        if(n == Integer.MIN_VALUE && x==2.0){
            return 0.0;
        }
        if (n>0){
            return doPow(x,n);
        }else if (n<0){
            return 1/doPow(x,-n);
        }else {
            return 1;
        }
    }

    public double doPow(double x,int n){
         if (n==0){
            return 1;
        }
        if(n==1){
            return x;
        }
        if (n%2==1){
            double half = doPow(x, n / 2);
            return half * half*x;
        }else {
            double half = doPow(x, n / 2);
            return half*half;
        }
    }
}

 

posted @ 2019-04-27 22:47  AshOfTime  阅读(225)  评论(0编辑  收藏  举报