《剑指offer》面试题16:数值的整数次方(C++实现)

题目描述

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

求数值的整数次方多简单哦,小老板,直接一手for循环,exponent个base相乘不就搞定了啊?
说干就干。

//case通过率40%
class Solution {
public:
    double Power(double base, int exponent) {
    double result = 1.0;
    for(int i = 1;i<=exponent;i++)
        result *=base; 
    return result;
    }
};

得到的输出结果是:

您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为40.00%

用例:
2,-3
对应输出应该为:
0.12500
你的输出为:
1.00000

原来是没有考虑指数为负数的情况啊。
再把代码进行修改。

//运行时间:4ms
//运行内存:456K
class Solution {
public:
    double Power(double base, int exponent) {
    double result = 1.0;
    for(int i = 1;i<=abs(exponent);i++)
        result *=base; 
    if(exponent<0) result = 1/result;//如果指数是负数 求结果的倒过来数
    return result;
    }
};

显示我通过了这道题。不过这样并不能让面试官满意。

解决思路

不过这道题的解决重点在于两个地方。
1.对指数整数范围的充分考虑,一般正数很好解决,负数和0怎么处理呢?
特别是可以提问,0的负整数次方还有00 没有意义,应当如何处理。
2.对于求正整数次方,除了for循环,还有别的更高效的计算方法。

思路一:补充布尔型标志位代表无效输入

//运行时间:4ms
//运行内存:456K
class Solution {
public:
    bool g_InvalidInput = false;//设置输入变量标志位,True代表出现0的非正整数次方计算
    double Power(double base, int exponent) {
    g_InvalidInput = false;
    
    if((base==0.0)&&exponent<=0)//计算0的非正整数次方,标志为为true,返回0.0
    {
        g_InvalidInput = true;
        return 0.0;
    }
    
    double result = PowerCompute(base,exponent);//获取base的真整数次方
    if(exponent<0) result = 1/result;//如果指数是负数 求结果的导数
    return result;
    }
    
    //计算base的正整数次方
    double PowerCompute(double base,int exponent)
    {
        double result = 1.0;
        for(int i = 1;i<=abs(exponent);i++)
            result *=base; 
        return result;
    }
};

思路二:用位运算符来提高我们的计算效率

如果我们求一个数字的32次方。除了用32个这个数字相乘。
我们还可以,求2数字的平方。在平方的基础上,求4次方。4次方的基础上,求8次方。8次方的基础上,求16次方。16次方的基础上,求32次方。
那么我们一定会用到下面的公式。

a n = { a n / 2 ∗ a n / 2 n为偶数 a ( n − 1 ) / 2 ∗ a ( n − 1 ) / 2 ∗ a n为奇数 a^n=\left\{ \begin{aligned} a^{n/2} * a^{n/2}&amp;&amp; \text{n为偶数}\\ a^{(n-1)/2} * a^{(n-1)/2} *a&amp;&amp; \text{n为奇数} \\ \end{aligned} \right. an={an/2an/2a(n1)/2a(n1)/2an为偶数n为奇数
那么我们需要对于计算base的正整数次方计算进行优化。(PowerCompute)
实现上述的方式使用递归。

//运行时间:3ms
//占用内存:480K
class Solution {
public:
    bool g_InvalidInput = false;//设置输入变量标志位,True代表出现0的非正整数次方计算
    double Power(double base, int exponent) {
    g_InvalidInput = false;
    
    if((base==0.0)&&exponent<=0)//计算0的非正整数次方,标志为为true,返回0.0
    {
        g_InvalidInput = true;
        return 0.0;
    }
    
    double result = PowerCompute(base,exponent);//获取base的真整数次方
    if(exponent<0) result = 1/result;//如果指数是负数 求结果的导数
    return result;
    }
    
    //计算base的正整数次方
    double PowerCompute(double base,int exponent)
    { 
        if(exponent==0)
            return 1;
        if(exponent==1)
            return base;
   
        double result =PowerCompute(base,exponent/2);
       //可替换代码1:double result =PowerCompute(base,exponent>>1);用右移运算符代替除以2//可能会显示超出内存
        result *=result;
        if(exponent%2)
        //可替换代码2:if(exponent &0x1 ==1) 用位与运算符代替求余运算符号
            result *= base;
        return result;
    }
};

小结

解决思路里虽然代码可以提交,但是对没有意义的输入没有考虑,代码不够鲁棒性。
思路一对非法输入做了补充,另外采用循环计算次方。
思路二相对于思路一而言,在计算次方上提升了计算效率,为所有思路中的最佳。

整体而言,思路二最佳。

参考文献

《剑指offer》

牛课网刷题链接link.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值