题目来源:LeetCode367:有效的完全平方数
问题抽象: 给定一个 正整数 num(值域 1 ≤ num ≤ 2^31-1),要求判断 num 是否可表示为某个 整数的平方(即完全平方数),满足以下核心需求:
-
判定规则:
- 存在整数
n满足n × n = num(n为非负整数); - 若存在则返回
true,否则返回false。
- 存在整数
-
计算约束:
- 时间复杂度 O(log num)(需避免暴力枚举
O(√num)); - 空间复杂度 O(1)(仅常数空间);
- 禁止使用内置平方根函数(如
sqrt)。
- 时间复杂度 O(log num)(需避免暴力枚举
-
数学特性:
- 完全平方数的二进制表示中 1 的数量有奇偶性规律(可辅助优化);
- 可通过 二分查找 或 牛顿迭代法 高效逼近整数解。
-
边界处理:
num=1时返回true(1=1²);num=2时返回false(无整数解);- 大数边界:
num=2147395600→true(46340²);num=2147483647(2^31-1)→false(非完全平方数);
- 特殊值:
num=16→true,num=14→false。
输入:正整数 num(1 ≤ num ≤ 2^31-1)。
输出:布尔值(true 表示是完全平方数,false 表示不是)。
解题思路
题目要求判断一个正整数 num 是否为完全平方数(即能表示为某个整数的平方)。不能使用内置的平方根函数,需要设计高效算法。核心思路如下:
- 特殊处理:当
num = 1时,直接返回true(因为 1 = 1 * 1)。 - 二分查找:
- 查找范围:平方根一定位于区间
[2, num/2]内(当 num ≥ 4 时成立)。这是因为:- 当 num ≥ 4 时,有 n u m \sqrt{num} num ≤ num/2(例如 num=4 时,( 4 \sqrt{4} 4=2=4/2);num=9 时, 9 \sqrt{9} 9=3 < 9/2=4.5)。
- 当 num=2 或 3 时,区间为
[2, 1](无效),直接跳过循环返回false。
- 查找过程:
- 计算中点
mid = left + (right - left) / 2(防溢出)。 - 用
long存储mid * mid避免整数溢出。 - 若
mid² = num,返回true;若mid² < num,说明mid太小,调整左边界;否则调整右边界。
- 计算中点
- 查找范围:平方根一定位于区间
- 终止条件:若循环结束未找到,返回
false。
代码实现(Java版)🔥点击下载源码
class Solution {
public boolean isPerfectSquare(int num) {
if (num == 1) {
return true; // 1 是完全平方数
}
long left = 2; // 左边界从2开始
long right = num / 2; // 右边界设为 num/2(整数除法)
while (left <= right) {
long mid = left + (right - left) / 2; // 防止溢出
long square = mid * mid; // 计算 mid 的平方
if (square == num) {
return true; // 找到完全平方数
} else if (square < num) {
left = mid + 1; // 平方太小,增大左边界
} else {
right = mid - 1; // 平方太大,减小右边界
}
}
return false; // 未找到符合条件的整数
}
}
代码说明
- 特殊处理:
num = 1时直接返回,避免不必要的计算。 - 二分边界:
- 左边界
left从2开始,因为num > 1时平方根最小为2(如 (4) 的平方根)。 - 右边界
right = num / 2,利用数学性质缩小搜索范围。
- 左边界
- 防溢出处理:
- 使用
long存储中间变量mid和square,防止大数计算时溢出(如mid * mid可能超出int范围)。 - 中点计算采用
left + (right - left) / 2而非(left + right) / 2,避免加法溢出。
- 使用
- 效率:二分查找时间复杂度为 O(\log n),空间复杂度 O(1),满足高效要求。
提交详情(执行用时、内存消耗)

1132

被折叠的 条评论
为什么被折叠?



