剑指Offer:数值的整数次方(C++)(含完整代码)

剑指Offer:数值的整数次方(C++)(含完整代码)

题目描述:

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0。

  • base=0 exponent<0 报错
  • base=0 exponent=0 未定义
  • base=0 exponent>0 结果为0
  • base!=0 exponent<0 1÷乘方
  • base!=0 exponent=0 结果为1
  • base!=0 exponent>0 乘方

解题时要考虑全面,若base!=0,则正常处理即可。若base=0,exponent>0,则结果为0;若exponent<0,这是非法的,分母不为0,所以程序应该报错;但牛客网对这个似乎要求不高,只要返回0也可。若exponent=0,这在数学中没有定义这种情况,所以该题说明了不同时为0,但若求职时,有必要和面试官讨论一下如果两个数都为0,我们把它定义为多少。下面这个AC代码我是把base=0的情况全考虑为结果为0。

AC代码:

class Solution
{
public:
    double Power(double base, int exponent)
    {
        return pow(base,exponent);
    }
};

这解法虽然也能AC,但这不是做题的目的,最好还是别用自带函数。

AC代码:

class Solution
{
public:
    double Power(double base, int exponent)
    {
        if(base==0)
            return 0;
        double result=1.0;
        for(int i=1; i<=fabs(exponent); i++)
            result=result*base;
        if(exponent<0)
            result=1.0/result;
        return result;
    }
};

虽然上面代码AC了,但还不是可以让面试官眼前一亮的代码。为什么,第一,对于base=0的三种情况考虑地不够细致;其次,base是double型,由于计算机表示小数(包括float和double型小数)都有误差,我们不能用等于(==)判断两个小数是否相等。如果两个小数的绝对值很小,比如小于0.0000001,就可以认为它们相等。因此上面代码还可以进行如下优化。

AC代码:

bool e_InvalidInput=false;
class Solution
{
public:
    double Power(double base, int exponent)
    {
        e_InvalidInput=false;//每次调用函数前确保为false,避免上一次的结果对本次特殊情况判断造成影响。
        if(equal(0.0,base)&&exponent<0)
        {
            e_InvalidInput=true;//如果输入非法的话,虽然返回0,但有全局变量e_InvalidInput的标记,就知道返回的0,是否是非法输入返回的0。
            return 0.0;
        }
        double absexponent;
        absexponent=exponent;
        if(exponent<0)
            absexponent=-exponent;
        double result=PowerWithExpoent(base,absexponent);
        if(exponent<0)
            result=1.0/result;
        return result;
    }
    double PowerWithExpoent(double base,int absexponent)
    {
        //若base为0,absexpoent大于0,结果为0;若base为0,absexpoent等于0,数学中无定义,但我们把它定义为结果为1,经过该函数计算结果为1。
        double result=1.0;
        for(int i=1; i<=absexponent; i++)
            result=result*base;
        return result;
    }
    bool equal(double num1,double num2)
    {
        if((num1-num2<0.0000001)&&(num1-num2)>-0.0000001)
            return true;
        else
            return false;
    }
};

这样就算最优了吗?当然不是,如果像上面那样循环来实现乘方,比较费时;例如2的32次方需要32次,但如果先计算2的平方,再求2的4次方,再求2的8次方,再求2的16次方,再求2的32次方省时得多。代码如下,需好好理解。

AC代码:

bool e_InvalidInput=false;
class Solution
{
public:
    double Power(double base, int exponent)
    {
        e_InvalidInput=false;//每次调用函数前确保为false,避免上一次的结果对本次特殊情况判断造成影响。
        if(equal(0.0,base)&&exponent<0)
        {
            e_InvalidInput=true;//如果输入非法的话,虽然返回0,但有全局变量e_InvalidInput的标记,就知道返回的0,是否是非法输入返回的0。
            return 0.0;
        }
        double absexponent;
        absexponent=exponent;
        if(exponent<0)
            absexponent=-exponent;
        double result=PowerWithExpoent(base,absexponent);
        if(exponent<0)
            result=1.0/result;
        return result;
    }
    double PowerWithExpoent(double base,int absexponent)
    {
        if(absexponent==0)
            return 1;
        if(absexponent==1)
            return base;
        double result=PowerWithExpoent(base,absexponent>>1);
        result=result*result;
        if((absexponent&1)==1)
            result=result*base;
        return result;
    }
    bool equal(double num1,double num2)
    {
        if(num1-num2<0.0000001&&num1-num2>-0.0000001)
            return true;
        else
            return false;
    }
};

完整代码:

#include
#include
using namespace std;
bool e_InvalidInput=false;
class Solution
{
public:
    double Power(double base, int exponent)
    {
        e_InvalidInput=false;//每次调用函数前确保为false,避免上一次的结果对本次特殊情况判断造成影响。
        if(equal(0.0,base)&&exponent<0)
        {
            e_InvalidInput=true;//如果输入非法的话,虽然返回0,但有全局变量e_InvalidInput的标记,就知道返回的0,是否是非法输入返回的0。
            return 0.0;
        }
        double absexponent;
        absexponent=exponent;
        if(exponent<0)
            absexponent=-exponent;
        double result=PowerWithExpoent(base,absexponent);
        if(exponent<0)
            result=1.0/result;
        return result;
    }
    double PowerWithExpoent(double base,int absexponent)
    {
        if(absexponent==0)
            return 1;
        if(absexponent==1)
            return base;
        double result=PowerWithExpoent(base,absexponent>>1);
        result=result*result;
        if(absexponent&1==1)
            result=result*base;
        return result;
    }
    bool equal(double num1,double num2)
    {
        if(num1-num2<0.0000001&&num1-num2>-0.0000001)
            return true;
        else
            return false;
    }
};
int main()
{
    Solution s;
    cout<<s.Power(0.1,2)<<endl;
    return 0;
}

运行结果:
在这里插入图片描述
永远相信美好

你可能感兴趣的:(剑指offer)