一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
题目描述
给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
进阶:不要 使用任何内置的库函数,如 sqrt 。
示例
输入: num = 16
输出: true
输入: num = 14
输出: false
提示
1 <= num <= 2^31 - 1
暴力法
由于不能使用内置的库函数,那么我们只好使用一个笨方法,将一个个数值进行相乘来比较,判断目标值是否为完全平方数。参考提示中给出的目标值范围,我们需要在一个个数值相乘的基础上做好边界的处理,不然会导致该方法超时。
class Solution {
public boolean isPerfectSquare(int num) {
// 边界判断
if(num == 1){
return true;
}
long sqrt = 2L;
// 如果该数值相乘的和超过目标值则不再比较后续的数值
while(sqrt * sqrt <= num){
// 目标值判断
if(sqrt * sqrt == num){
return true;
}
// 不符合,数值自增 1
++sqrt;
}
return false;
}
}
二分法
暴力法需要一个个数值进行比较,如果目标值太大的话,需要话费的时间太多了。那么我们能不能使用二分法来进行优化呢?
- 获取数值边界【1,num】
- 取中间值,判断其相乘结果大于或小于目标值,然后移动边界,排除掉一半的元素
- 重复步骤2,直至找到目标值或者停止循环
- 返回结果
class Solution {
public boolean isPerfectSquare(int num) {
// 确定左右两个边界
int left = 0, right = num;
// 终止条件
while (left <= right) {
// 取得中间值
int mid = left + (right - left) / 2;
// 计算相乘的结果
long sqrt = (long) mid * mid;
// 等于目标值,返回
if(sqrt == num){
return true;
}else if(sqrt > num){
// 大于目标值,右边边界左移
right = mid - 1;
}else{
// 小于目标值,左边边界右移
left = mid + 1;
}
}
// 不符合,返回结果
return false;
}
}