幂相关专题

概述

主要涉及二分查找,牛顿迭代法
如果用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. 平方数之和

先放着

猜你喜欢

转载自blog.csdn.net/hhmy77/article/details/115224526