剑指offer_面试题16 : 数值的整数次方( python实现 )

数值的整数次方( python实现 )

一、题目描述

题目:数值的整数次方
实现函数 double Power(double base, int exponent),求 base 的 exponent 次方。不得使用库函数,同时不需要考虑大数问题。

二、解题思路

  暂略。(此处主要作为书中python实现补充)

三、代码实现

  题目中明确给出,不需要考虑大数问题,即不考虑溢出问题。不过,我们在这里还是需要考虑一些特殊情况。比如 b a s e base base 为0时, e x p o n e n t exponent exponent 为负数,此时若是采用先求出 b a s e base base e x p o n e n t exponent exponent 的绝对值次方,即 r e s u l t = b a s e ∣ e x p o n e n t ∣ result = base^{|exponent|} result=baseexponent,然后利用 r e s u l t = 1 / r e s u l t result = 1 / result result=1/result,就会出现 1/0 的情况,而导致出错。(当然题目给出 e x p o n e n t exponent exponent i n t int int 类型,所以也不需要考虑指数为小数)

  以下利用 python 代码简单实现了题目的要求,并针对特殊情况做了处理,具体如下:

def power(base, exponent):
    if base == 0 and exponent < 0:
        return False
    result = 1.0
    for i in range(abs(exponent)):
        result = base * result
    if exponent < 0:
        result = 1.0 / result
    return result

  对上述代码进行简单的测试,如下。

>>> power(3, 3)
Out:
27.0
>>> power(0, 3)
Out:
0.0
>>> power(2, -2)
Out:
0.25
>>> power(0, -2)
Out:
False

  在面试过程中,对代码做进一步优化,总是我们所追求的。例如,若 exponent 为 32,按照上面 power 函数的做法,for 循环中要进行31次乘法。若是换一种思路思考: b a s e 32 base^{32} base32 等于 b e s e 16 bese^{16} bese16 的二次方, b e s e 16 bese^{16} bese16 又是 b e s e 8 bese^{8} bese8 的二次方。以此类推,做 32 次方只需 5 次乘法,先求2次方,然后4次方,然后8次方,再然后16次方,最终求得32次方。

  可以用以下公式来求 a 的 n 次方:

a n = { a n / 2 ⋅ a n / 2 n 为 偶 数 a ( n − 1 ) / 2 ⋅ a ( n − 1 ) / 2 ⋅ a n 为 奇 数 a^{n} = \left\{\begin{matrix} a^{n/2} \cdot a^{n/2} & n为偶数 \\ a^{(n-1)/2} \cdot a^{(n-1)/2} \cdot a & n为奇数 \end{matrix}\right. an={an/2an/2a(n1)/2a(n1)/2ann

  以上公式,其实很容易用递归实现,如下:


def powerAdvanced(base, exponent):
    if base == 0 and exponent < 0:
        return False
    result = 1.0
    # 将之前power函数中的for循环替换成以下递归函数
    result = powerWithUnsignedExponent(base, abs(exponent))
    if exponent < 0:
        result = 1.0 / result
    return result

# powerWithUnsignedExponent主要对无符号数求结果
def powerWithUnsignedExponent(base, exponent):
    if exponent == 0:
        return 1.0
    elif exponent == 1:
        return base
    result = powerWithUnsignedExponent(base, exponent>>1)
    result = result * result
    if exponent & 0x1 ==1:
        result = result*base
    return result

  这里对于普通用例的测试结果与前面一致,不再做演示。不过我们可以一起来看看两者运算效率的比较。

import time
time_start = time.time()
for i in range(10000):
    power(1,10000)
time_end = time.time()
print("The total time of power is",time_end-time_start)

time_start = time.time()
for i in range(10000):
    powerAdvanced(1,10000)
time_end = time.time()
print("The total time of powerAdvanced is",time_end-time_start)
Out:
The total time of power is 9.405900239944458
The total time  of powerAdvanced is 0.06249380111694336

  以上结果可明显看出,其运算效率确有很大提升。

  扩展:当然,递归程序也可以进一步改写成循环实现,python 实现如下(仅供参考)。

def powerAdvancedBaseLoop(base, exponent):
    if base == 0 and exponent < 0:
        return False
    result = powerWithUnsignedExponent(base, abs(exponent))
    if exponent < 0:
        result = 1.0 / result
    return result
    
def powerWithUnsignedExponent(base, exponent):
    temp = []
    result = base
    if exponent == 0:
        return 1.0
    elif exponent == 1:
        return base
    while exponent > 1:
        temp.append(exponent)
        exponent = exponent>>1
    while len(temp):
        temp_exponent = temp.pop()
        result = result * result
        if temp_exponent & 0x1 == 1:
            result = result*base
    return result
import time
time_start = time.time()
for i in range(10000):
    powerAdvanced(1,10000)
time_end = time.time()
print("The total time of powerAdvanced is",time_end-time_start)

time_start = time.time()
for i in range(10000):
    powerAdvancedBaseLoop(1,10000)
time_end = time.time()
print("The total time of powerAdvancedBaseLoop is",time_end-time_start)
The total time of powerAdvanced is 0.03191518783569336
The total time of powerAdvancedBaseLoop is 0.03393840789794922

你可能感兴趣的:(经典算法实现,算法面试,算法面试题)