leetcode
leetcode 301 ~ 350
有效的完全平方数

有效的完全平方数

难度:

标签:

题目描述

给你一个正整数 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 <= num <= 231 - 1

代码结果

运行时间: 17 ms, 内存: 16.0 MB


/*
 * 思路:
 * 使用Java Stream的范围和函数式编程特性来实现。
 * 我们可以在IntStream.rangeClosed(1, num/2+1)的范围内进行遍历,
 * 然后通过mapToLong(i -> (long)i * i)计算平方,
 * 如果找到等于num的情况,则返回true。
 */
import java.util.stream.IntStream;
 
public class SolutionStream {
    public boolean isPerfectSquare(int num) {
        return IntStream.rangeClosed(1, num / 2 + 1)
                .mapToLong(i -> (long) i * i)
                .anyMatch(square -> square == num);
    }
}

解释

方法:

这个题解使用二分查找的方法来判断一个数是否为完全平方数。具体思路如下: 1. 如果给定的数num等于1,直接返回True,因为1是完全平方数。 2. 初始化左边界l为1,右边界r为num-1。 3. 当l<=r时,进行以下循环: a. 计算中间值mid为(l+r)//2。 b. 如果num除以mid的结果等于mid,说明找到了完全平方数,返回True。 c. 如果num除以mid的结果小于mid,说明mid太大,将右边界r更新为mid-1。 d. 否则,num除以mid的结果大于mid,说明mid太小,将左边界l更新为mid+1。 4. 如果循环结束没有找到完全平方数,返回False。

时间复杂度:

O(log n)

空间复杂度:

O(1)

代码细节讲解

🦆
您在题解中的二分查找算法中提到如果`num / (mid * 1.0) == mid`则返回True,但考虑到浮点数的精度问题,这种比较是否总是准确的?
在使用浮点数进行比较时,确实存在精度问题,尤其是当数字非常大时。在本题的上下文中,更安全的做法是避免使用浮点数比较。可以改为使用整数操作,例如检查`mid * mid == num`,这样可以精确地判断mid的平方是否等于num,无需担心浮点数的精度问题。
🦆
在二分查找的过程中,您提到如果`num / mid < mid`则右移右边界到`mid - 1`,请问这样的更新逻辑是否有可能跳过真正的完全平方数?
这种更新逻辑是安全的,不会跳过真正的完全平方数。当`num / mid < mid`时,意味着`mid * mid > num`,因此mid太大了。将右边界移动到`mid - 1`是正确的,因为任何大于或等于mid的数平方后都会大于num,不可能是我们要找的完全平方数。这个逻辑确保了不会错过正确的答案。
🦆
您的算法中为什么选择将右边界`r`初始化为`num - 1`而不是`num`,这样的初始化对查找的效率和结果有什么影响?
初始化右边界`r`为`num - 1`是因为我们已经处理了`num`等于1的情况,对于所有大于1的`num`,其完全平方根不会等于`num`本身,因此没必要将`num`作为右边界。这样做能够稍微提升效率,因为减少了搜索范围,但在大多数情况下对结果的影响不大,主要是减少了不必要的比较。
🦆
给定的提示中`num`的最大值是`2^31 - 1`,在这种情况下,mid的计算可能会导致整型溢出。您的代码中如何处理这种可能的溢出问题?
在Python中,整数类型是动态扩展的,因此理论上不会发生整型溢出问题。但在其他某些编程语言中(如Java或C++),这可能是一个问题。为了避免整型溢出,可以使用`mid = l + (r - l) / 2`来代替`mid = (l + r) / 2`。这种方法可以避免在计算mid时l和r的和超出整数的最大范围。

相关问题

x 的平方根

给你一个非负整数 x ,计算并返回 x 的 算术平方根

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5

 

示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

 

提示:

  • 0 <= x <= 231 - 1

平方数之和

给定一个非负整数 c ,你要判断是否存在两个整数 ab,使得 a2 + b2 = c

 

示例 1:

输入:c = 5
输出:true
解释:1 * 1 + 2 * 2 = 5

示例 2:

输入:c = 3
输出:false

 

提示:

  • 0 <= c <= 231 - 1