数值的整数次方
描述:
实现函数 double Power(double base, int exponent),求 base 的 exponent 次方。
注意:
1.保证base和exponent不同时为0。
2.不得使用库函数,同时不需要考虑大数问题
3.有特殊判题,不用考虑小数点后面0的位数。
我的思路:直接使用递归,让它每次乘一个它自身。但这存在一个问题,如果这个
e
x
p
o
n
e
n
t
exponent
exponent 是负数怎么办?
一下是参考别人的题解:
方法1:直接运算
不断做累乘,重点是处理负的次方数,
x
−
n
=
(
1
x
)
n
x^{-n}=(\frac{1}{x})^n
x−n=(x1)n ,所以我们要将 底数转换为相应的分数,再见次方数转换回正数即可。
时间复杂度:
O
(
n
)
O(n)
O(n) ,空间复杂度:
O
(
1
)
O(1)
O(1)
class Solution:
def Power(self , base: float, exponent: int) -> float:
# write code here
# 如果基数是0,那么不管多少次方都是0
if base == 0:
return float(0)
res = base
# 指数大于0
if exponent > 0:
for i in range(exponent-1):
res *= base
# 指数等于0
elif exponent == 0:
res = float(1)
# 指数小于0
else:
# 将指数换成相反数
exponent = -exponent
# 底数换成原底数的-1次方
base = 1 / base
# 所有结果已经保留了一次结果
res = base
for i in range(exponent-1):
res *= base
return res
看了别人的代码进行了一点点精简。
class Solution:
def Power(self , base: float, exponent: int) -> float:
if exponent < 0:
base = 1 / base
exponent = -exponent
res = 1.0
for i in range(exponent):
res *= base
return res
方法2:快速幂
使用的是分治思想,分治即“分而治之”,“分”指的是将一个大而复杂的问题划分成多个性质相同但是规模更小的子问题,子问题继续按照这样划分,直到问题可以被轻易解决;“治”指的是将子问题单独进行处理。经过分治后的子问题,需要将解进行合并才能得到原问题的解,因此整个分治过程经常用递归来实现。
解题思路:幂运算,我们可以采用快速幂。如果我们要计算
5
10
5^{10}
510 ,常规算法是
5
∗
5
=
25
,
25
∗
5
=
125
,
.
.
.
,
5*5=25, 25*5=125, ...,
5∗5=25,25∗5=125,..., 以此类推,一共经过9次运算,即
n
−
1
n-1
n−1 次。但是,如果我们考虑:
5
∗
5
=
25
(
二次
)
5*5=25(二次)
5∗5=25(二次)、
25
∗
25
=
625
(
四次
)
25*25=625(四次)
25∗25=625(四次)、
625
∗
625
=
.
.
.
(
八次
)
625*625=...(八次)
625∗625=...(八次) ,利用这个二分的思路,运算次数就缩减到
l
o
g
2
n
log_2n
log2n 次,公式如下:
x
n
=
{
x
n
2
∗
x
n
2
n为偶数
x
n
−
1
∗
x
n为奇数
1
n=0
x^n=\begin{cases} x^{\frac{n}{2}} * x^{\frac{n}{2}}& \text{n为偶数}\\ x^{n-1} * x & \text{n为奇数}\\ 1 & \text{n=0} \end{cases}
xn=⎩
⎨
⎧x2n∗x2nxn−1∗x1n为偶数n为奇数n=0
举个例子:
2
10
2^{10}
210 的求取过程(图片来自牛客某位大佬的解析,感觉挺不错的,保留截图该图片便于理解)
时间复杂度:
O
(
l
o
g
2
n
)
O(log_2n)
O(log2n),空间复杂度:
O
(
1
)
O(1)
O(1)
# 快速幂计算法
def pow(x: float, y: int)->float:
res = 1
while y:
# 位与运算
if y & 1:
res *= x
# 叠加,每次都将
x *= x
# 减少乘次数
# 右移,y值每次减少一半,
y = y >> 1
return res
def Power(base: float, exponent: int)->float:
# 处理负数次方
if exponent < 0:
exponent = -exponent
base = 1 / base
res = 1.0
return Power(base, exponent)