文章目录
概述
主要涉及二分查找,牛顿迭代法
如果用python来解题就不用担心溢出问题,能省很多事
题目
50.Pow(x, n)
69. x 的平方根
367. 有效的完全平方数
372. 超级次方
633. 平方数之和
50. Pow(x, n)
需要处理的是n<=0的状态
如果n=0,那么返回1
如果n<0,那么取x的倒数,再乘
朴素解法 未通过
class Solution:
def myPow(self, x: float, n: int) -> float:
if n == 0 :
return 1
if n<0:
x = 1/x
n = -n
s = x
while n-1:
x *= s
n -= 1
return x
O ( n ) O(n) O(n)的时间复杂度超时了
快速幂 递归
快速幂的时间复杂度 O ( l o g n ) O(logn) O(logn) 能够通过这道题
class Solution:
def fast(self,x,n):
if n == 0:
return 1
half = self.fast(x,n//2)
if n % 2 == 0:
return half*half
else:
return half*half*x
def myPow(self, x: float, n: int) -> float:
if n == 0 :
return 1
if n<0:
x = 1/x
n = -n
return self.fast(x,n)
快速幂基于这样的思想:
快速幂 迭代
直接贴leetcode的题解了,讲得很清楚
class Solution:
def fast(self,x,N):
ans = 1.0
# 贡献的初始值为 x
x_contribute = x
# 在对 N 进行二进制拆分的同时计算答案
while N > 0:
if N % 2 == 1:
# 如果 N 二进制表示的最低位为 1,那么需要计入贡献
ans *= x_contribute
# 将贡献不断地平方
x_contribute *= x_contribute
# 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可
N //= 2
return ans
def myPow(self, x: float, n: int) -> float:
if n<0:
x = 1/x
n = -n
return self.fast(x,n)
迭代的快速幂并不难写,记住规律就行了(不太好表述,但是很直观)
求x的n次方ans,那么把n展开成2进制,然后对于n的2进制判断,如果最低位是1,那么乘上x,不断把n减半,把x乘等于x,最后ans就是答案
69. x的平方根
二分
很容易想到二分法
class Solution:
def mySqrt(self, x: int) -> int:
lo,hi = 0,x
while lo<=hi:
mid = (hi+lo)//2
if mid*mid <= x:
ans = mid
lo = mid+1 # 继续逼近
else:
hi = mid-1 # 缩小范围
return ans
时间复杂度 O ( l o g x ) O(logx) O(logx)
下面记录一下其它解法
转换为e
由于浮点数有误差,所以最后要确认ans还是ans+1是最终答案
class Solution:
def mySqrt(self, x: int) -> int:
if x == 0:
return 0
ans = int(math.exp(0.5 * math.log(x)))
return ans + 1 if (ans + 1) ** 2 <= x else ans
时间复杂度可以视为 O ( 1 ) O(1) O(1)
牛顿迭代法
class Solution:
def mySqrt(self, x: int) -> int:
if x == 0:
return 0
C, x0 = float(x), float(x)
while True:
xi = 0.5 * (x0 + C / x0)
if abs(x0 - xi) < 1e-7:
break
x0 = xi
return int(x0)
时间复杂度 O ( l o g x ) O(logx) O(logx),但是比二分查找收敛得更快
367. 有效的完全平方数
二分
依然是二分的思想,最终ans会得到最接近于sqrt(num)
的数,然后我们判断两者关系即可
class Solution:
def isPerfectSquare(self, num: int) -> bool:
lo,hi = 0,num
while lo<=hi:
mid = (hi+lo)//2
if mid*mid<=num:
ans = mid
lo = mid+1
else:
hi = mid-1
return ans*ans == num
牛顿迭代法
还是一样的思想,快速逼近到等于sqrt(num)
的最大整数x,然后判断两者关系
class Solution:
def isPerfectSquare(self, num: int) -> bool:
if num < 2:
return True
x = num // 2
while x * x > num:
x = (x + num // x) // 2
return x * x == num
372. 超级次方
暂时想不到怎么做,先放着
633. 平方数之和
先放着