Python面试宝典第37题:有效的完全平方数

题目

        完全平方数是一个可以写成某个整数的平方的整数,换句话说,它可以写成某个整数和自身的乘积。现给你一个正整数num,如果num是一个完全平方数,则返回true,否则返回false。

        注意:不能使用任何内置的库函数(比如:sqrt)。

        示例 1:

输入:num = 16
输出:true
解释:返回true,因为4 * 4 = 16,且4是一个整数。

        示例 2:

输入:num = 14
输出:false
解释:返回false,因为3.742 * 3.742 = 14,但3.742不是一个整数。

暴力法

        暴力法求解一个数是否为完全平方数的基本思想是:通过遍历所有可能的平方根,来确定是否存在一个整数的平方恰好等于给定的数。使用暴力法求解本题的主要步骤如下。

        1、初始化i为1。

        2、当i * i <= num时,重复以下操作。

        (1)如果i * i == num,则返回True,表示num是一个完全平方数。

        (2)否则,增加i的值,并继续循环。

        3、如果循环结束而没有找到符合条件的i,则返回False,表示num不是一个完全平方数。

        根据上面的算法步骤,我们可以得出下面的示例代码。

def is_perfect_square_by_brute_force(num):
    if num < 1:
        return False
    
    i = 1
    while i * i <= num:
        if i * i == num:
            return True
        i += 1
        
    return False

print(is_perfect_square__by_brute_force(16))
print(is_perfect_square__by_brute_force(14))

二分搜索法

        二分搜索法的基本思想是:通过不断地将搜索区间对半分割来缩小搜索范围,直到找到目标值或确定目标值不存在。使用二分搜索法求解本题的主要步骤如下。

        1、初始化搜索区间为[1, num]。

        2、当搜索区间有效时(即左端点不大于右端点),计算区间的中间值mid,并重复进行如下操作。

        (1)如果mid * mid == num,则返回True,表示num是一个完全平方数。

        (2)如果mid * mid < num,则更新左端点为mid + 1。

        (3)如果mid * mid > num,则更新右端点为mid - 1。

        3、如果搜索结束后仍未找到符合条件的mid,则返回False,表示num不是一个完全平方数。

        根据上面的算法步骤,我们可以得出下面的示例代码。

def is_perfect_square_by_binary_search(num):
    if num < 1:
        return False

    left, right = 1, num
    while left <= right:
        mid = (left + right) // 2
        square = mid * mid
        
        if square == num:
            return True
        elif square < num:
            left = mid + 1
        else:
            right = mid - 1

    return False

print(is_perfect_square_by_binary_search(16))
print(is_perfect_square_by_binary_search(14))

牛顿迭代法

        牛顿迭代法是一种用于求解方程近似根的迭代方法,对于本问题,我们可以使用牛顿迭代法来逼近num的平方根。如果最终逼近的值的平方等于num,则num是一个完全平方数。使用牛顿迭代法求解本题的主要步骤如下。

        1、初始化猜测值x为num / 2或者1,这取决于num的大小。

        2、使用牛顿迭代公式,更新猜测值为x = (x + num / x) / 2。

        3、重复步骤2,直到x的变化非常小,或者x的平方等于num。

        4、如果最终x的平方等于num,则返回True,表示num是一个完全平方数。否则,返回False。

        根据上面的算法步骤,我们可以得出下面的示例代码。

def is_perfect_square_by_newton_method(num):
    if num < 1:
        return False

    # 初始化猜测值
    x = num
    if num < 3:
        x = 1

    # 设置精度阈值
    precision = 1e-10

    # 牛顿迭代
    while True:
        new_x = (x + num / x) / 2
        if abs(new_x - x) < precision or new_x * new_x == num:
            break
        x = new_x

    return int(x) * int(x) == num

print(is_perfect_square_by_newton_method(16))
print(is_perfect_square_by_newton_method(14))

总结

        使用暴力法时,我们需要从1开始逐步增加i,直到i * i > num,故其时间复杂度为O(n的平方根)。暴力法的优点是实现简单,易于理解,但效率较低,特别是对于较大的num。

        使用二分搜索法时,搜索区间每次减半,因此时间复杂度为O(logn)。相对于暴力法,二分搜索法的效率更高,且实现并不复杂。

        牛顿迭代法的收敛速度非常快,通常只需要几次迭代就可以达到很高的精度,其时间复杂度为O(log(log n))。牛顿迭代法的效率非常高,尤其在num较大时,表现更佳。

💡 需要《Python面试宝典》完整源码的大佬们,可订阅专栏后,搜索微信公众号“希望睿智”私信获取。

评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

希望_睿智

您的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值