zoukankan      html  css  js  c++  java
  • 数值的整数次方

    这是《剑指offer》里的一道题,内容是给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
    多年没怎么刷过题的我,第一眼感觉就是这题用最简单的乘法做下去肯定是对的,但可能效率堪忧。当然要考虑一些特殊情况,比如是exponent是0或负数,base是0或1之类的:

    def pow(base, exponent):
        if base in (0.0, 1.0):
            return base
        if exponent == 0:
            return 1.0
        num = 1.0
        for i in xrange(abs(exponent)):
            num *= base
        return num if exponent > 0 else 1.0/num
    

    其实这道题的代码是可以优化的。可以想象一下,假设我们要求(a^9)。我们可以根据二进制将9进行分解,9=42+1,那么如果我们能算出(a^4),就可以反推出(a^9)了。同理,我们要算(a^4),因为4=22,因此只要我们知道(a^2),就可以算出(a^4)了。由a推出(a^2)则很明显。那么实际上的计算量就是(a^9 = a^4 * a^4 * a, a^4=a^2 * a^2, a^2 = a * a),一共是4次乘法。这比直接算9次a的乘法可简单太多了。
    其实有了以上思路,不难写出一个递归的算法。不过这里我打算写一个非递归的做法。基本思路是:对exponent一边除2一边入栈,如果当前的值是奇数的话入栈的数为1,否则为0,一直除到exponent为0。然后再出栈反推回(base^{exponent}),根据出栈的值为0或1决定是否要多乘一次a,最终可反推出结果。
    具体的运行过程我画了幅图:

    def pow(base, exponent):
        if base in (0.0, 1.0):
            return base
        if exponent == 0:
            return 1.0
        num = 1.0
        stack = []
        abs_exponent = abs(exponent)
        while abs_exponent:
            stack.append(1 if abs_exponent % 2 else 0)
            abs_exponent = abs_exponent >> 1
        
        for i in xrange(len(stack)-1,-1,-1):
            num = num * num
            if stack[i]:
                num *= base
        return num if exponent > 0 else 1.0/num
    

    通过这种方法就可以将一个原本O(n)的算法优化为O(logN)。这也告诉我们:在写代码时可以考虑一下能否重用或递推已有的计算结果,这样往往可以使得代码运行效率更高。

  • 相关阅读:
    第01组 Beta冲刺(4/4)
    第01组 Beta冲刺(3/4)
    2019年安徽省黄山与湖北省武汉空气质量的数据分析
    爬取2019年hg录取分数线
    简单介绍下gbk和utf-8这两种编码的区别
    词云大作业(普哥、硕哥快来看啊!!!)
    分享一种下载python第三方库wordcloud库的一种方法
    介绍一种安装python第三方库jieba库的方法
    《C语言程序设计》实验报告(六)
    《C语言程序设计》实验报告(五)
  • 原文地址:https://www.cnblogs.com/wickedpriest/p/14321633.html
Copyright © 2011-2022 走看看