一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情
给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false
进阶:不要 使用任何内置的库函数,如 sqrt
示例 1:
输入:num = 16
输出:true
示例 2:
输入:num = 14
输出:false
提示:
1 <= num <= 2^31 - 1
解题思路:
这道题我们可以选择使用二分查找来做
具体思路:
-
因为一个数的项再大不可能是数值本身(1除外),我们就可以将区间范围限定在 1到num 中,进行二分查找
-
判断每次取到的中间值(这里先说明下:
mid是中间值,num是题目需要我们所判断的数,left是左指针,从1开始;right是右指针,从num开始
- 如果
num / mid == mid且mid mid == num,num就是一个完全平方数 - 如果
num / mid > mid,说明中间值mid比我们要找的项小,因此mid前面的数都不需要了,包括mid本身 ,左指针left移动到mid的 后一位,即left = mid + 1; - 如果
num / mid < mid,说明中间值mid比我们要找的项大,因此mid后面的数都不需要了,包括mid本身,右指针right移动到mid的 前一位,即right = mid - 1;
代码实现:(java)
//这里是当num为0和2时,都不是完全平方数,我们可以直接返回false
if (num == 0 || num == 2) {
return false;
}
if (num == 1) {
return true;
}
int left = 1;
int right = num;
while (left <= right) {
int mid = left + (right - left)/2;
//这里需要判断两次的原因是因为有的数除以项后,明明有余数,系统会忽略到余数,取比较靠左的项,这样明显不严谨
//所以我们由加了一次判断,判断 项相乘 是否等于num
//就拿5来说,5/2 = 2,2 == mid ,就会返回 true,但结果明显不对,所以我们就要再判断下2*2是否等于5
if (num / mid == mid) {
if (mid * mid == num) {
return true;
}else {
return false;
}
}else if (num / mid < mid) {
right = mid - 1;
}else if (num / mid > mid) {
left = mid + 1;
}
}
return false;
复杂度分析:
- 时间复杂度:O(log n)
- 空间复杂度:O(1) 输出