题解 | #数值的整数次方#

数值的整数次方

http://www.nowcoder.com/practice/1a834e5e3e1a4b7ba251417554e07c00

描述

这是一篇面对初级coder的题解。
知识点:数学常识 快速幂 递归
难度:一星


题解

题目:

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

保证base和exponent不同时为0。不得使用库函数,同时不需要考虑大数问题,也不用考虑小数点后面0的位数。

即求:浮点数的整数次方

首先补充一些数学上的基础知识:

a0=1 任何数的0次方得1

m-n=(1/m)一个数的负数次方就是一个数的正数次方的倒数

故有下面的预处理函数:

    if(exponent==0)
        return 1;
    if(exponent<0)
    {
        base=1/base;
        exponent=-exponent;
    }


方法一:暴力求解

按照乘方的定义 就是连续n个数相乘
class Solution {
public:
    double Power(double base, int exponent) {
    if(exponent==0)
        return 1;
    if(exponent<0)
    {
        base=1/base;
        exponent=-exponent;
    }
     double answer=1 ;//连乘 故初始化为1
     for(int i=0; i<exponent;i++)
         answer*=base;
    return answer;
    }
};
运行时间: 8 ms 占用内存:520K
显然,这样执行效率不高 其他语言也类似 需要更好的方法
时间复杂度O(n)

方法二:递归分治的思想

基于的原理如下 若n为偶数 a^n=a^(n/2)*a^(n/2) 若n为奇数 a^n=a^(n/2)*a^(n/2)*a 注意此处的除法为整除 之所以不用除法是为了提高效率
class Solution {
public:
    double Power(double base, int exponent) {
    if(exponent==0)
        return 1;
    if(exponent<0)
    {
        base=1/base;
        exponent=-exponent;
    }
    return Dpower(base,exponent);
    }
    double Dpower(double b, int n) {
        if (n == 1) 
            return b;
        double ret = Dpower(b, n/2);
        if (n&1)  // 奇数
            return ret * ret * b;
        else 
            return ret * ret;
    }
};

递归受递归深度限制,同时大家知道,递归虽然简洁,但会产生额外的空间开销。我们可以把递归改写为循环,来避免对栈空间的大量占用
运行时间: 4 ms 占用内存:524K
时间复杂度:O(logn),每次规模减少一半

空间复杂度:O(logn),递归栈,因为要记住logn个变量

方法三:快速幂

本质上采用了数的二进制表示方法 如求7的10次方,但这次,我们把10写成二进制的形式,也就是 1010 即10=0*2^0+1*2^1+0*2^2+1*2^3 考虑a(m+n)=am*an 7^10=7^2^1+7^2^3
class Solution {
public:
    double Power(double base, int exponent) {
    if(exponent==0)
        return 1;
    if(exponent<0)
    {
        base=1/base;
        exponent=-exponent;
    }
    double answer = 1;
    while(exponent){
        if(exponent&1)        //如果n的当前末位为1
            answer *= base;  //ans乘上当前的a
        base *= base;        //a自乘
        exponent >>= 1;       //n往右移一位
    }
    return answer;
    }
};
运行时间: 4 ms 占用内存:512K
时间复杂度:O(logn),因为n的二进制位个数为logn
空间复杂度:O(1)

参考《STL源码剖析》中 Pow函数在STL中的实现——方法是类似的
templateinline T identity_element(plus){
	return T(0);
}
 
templateinline T identity_element(multiplies){
	return T(1);
}
 
templateinline T power_this(T x, Integer n){
	return power_this(x, n, multiplies());
}
 
templateT power_this(T x, Integer n, MonoidOperation op){
	if (n == 0)
		return identity_element(op);
	else{
		while ((n & 1) == 0){
			n >>= 1;
			x = op(x, x);
		}
		T result = x;
		n >>= 1;
		while (n != 0){
			x = op(x, x);
			if ((n & 1) != 0)
				result = op(result, x);
			n >>= 1;
		}
		return result;
	}
}
identity_element(op)为取“证同元素”。所谓“运算op的证同元素”,意思是数值A若与该元素做op运算,会得到A自己。加法的证同元素为0,因为任何元素加上0仍为自己。乘法的证同元素为1,因为任何元素乘以1仍为自己。

总结

以2的7次方为例 三种方法总结如下:

可以看做是JZ11的升级版,二进制的数据本身就包含了很多信息
另:数学不好真玩不转计算机

扩展

快速幂的应用广泛
如下面例题中求矩阵的快速幂
阿Q的题解 文章被收录于专栏

阿Q秋招刷过的题

全部评论
0乘以任何数都为0,总结里面第三个为0?
点赞 回复 分享
发布于 2023-03-25 15:53 广东

相关推荐

06-13 17:33
门头沟学院 Java
顺序不记了,大致顺序是这样的,有的相同知识点写分开了1.基本数据类型2.基本数据类型和包装类型的区别3.==和equals区别4.ArrayList与LinkedList区别5.hashmap底层原理,put操作时会发生什么6.说出几种树型数据结构7.B树和B+树区别8.jvm加载类机制9.线程池核心参数10.创建线程池的几种方式11.callable与runnable区别12.线程池怎么回收线程13.redis三剑客14.布隆过滤器原理,不要背八股,说说真正使用时遇到了问题没有(我说没有,不知道该怎么回答了)15.堆的内存结构16.自己在写项目时有没有遇见过oom,如何处理,不要背八股,根据真实经验,我说不会17.redis死锁怎么办,watchdog机制如何发现是否锁过期18.如何避免redis红锁19.一个表性别与年龄如何加索引20.自己的项目的QPS怎么测的,有没有真正遇到大数量表21.说一说泛型22.springboot自动装配原理23.springmvc与springboot区别24.aop使用过嘛?动态代理与静态代理区别25.spring循环依赖怎么解决26.你说用过es,es如何分片,怎么存的数据,1000万条数据怎么写入库中27.你说用limit,那么在数据量大之后,如何优化28.rabbitmq如何批次发送,批量读取,答了延迟队列和线程池,都不对29.计网知不知道smtp协议,不知道写了对不对,完全听懵了30.springcloud知道嘛?只是了解反问1.做什么的?短信服务,信息量能到千万级2.对我的建议,基础不错,但是不要只背八股,多去实际开发中理解。面试官人不错,虽然没露脸,但是中间会引导我回答问题,不会的也只是说对我要求没那么高。面完问我在济宁生活有没有困难,最快什么时候到,让人事给我聊薪资了。下午人事打电话,问我27届的会不会跑路,还在想办法如何使我不跑路,不想扣我薪资等。之后我再联系吧,还挺想去的😭,我真不跑路哥😢附一张河科大幽默大专图,科大就是大专罢了
查看30道真题和解析
点赞 评论 收藏
分享
07-18 18:05
门头沟学院 Java
挂了&nbsp;正式批求捞
投递滴滴等公司10个岗位
点赞 评论 收藏
分享
评论
2
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务