这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战
有效的完全平方数
该题出自力扣的367题——有效的完全平方数(简单题),题解消化于官方
审题
给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
进阶:不要 使用任何内置的库函数,如 sqrt
-
简单总结就是,找出一个数是否可以被开根号为整数,也就是 X * X = num
-
方法还是挺多的:
-
如果忽略题目里面那句进阶的话,那就可以用内置的库函数sqrt
当然了,这样有点挑战力扣的编译器.....public static boolean isPerfectSquare(int num) { double x = Math.sqrt(num) return x * x == num; } -
除开这个内置方法,还可以直接暴力循环,从0开始,极限是num本身;
- 时间复杂度是O(根号 n )其中 n 为正整数 num 的最大值。我们最多需要遍历 根号 n + 1 个正整数。
- 空间复杂度是O(1)
-
二分查找:
- 从0开始,极限为num本身,利用二分查找的方式
- 一旦 mid * mid == num 就代表存在
-
还有一种数学方法:牛顿迭代法,emmmmm,因为我掌握不住,所以就不在这里声明了
-
编码
- 在最开始编码的时候,虽然思路是对的——典型的二分查找;但是却在一些地方没有把握好细节,容易导致力扣的超时
- 计算中间值 mid:最开始会直接用(left +right)/ 2,但是在数据量大的情况下容易导致溢出
- 计算target—— num * num的时候;如果直接用int去接收,也会导致超时溢出;因为部分的测试用例会数据范围较大;而int 的最大为11位;num * num 下,target就会溢出
- 所以这个地方需要强转Long型
public static boolean isPerfectSquare(int num) {
//二分查找
int left = 0;
int right = num;
while (left <= right){
int mid = left+(right-left)/2;
long target = (long) mid * mid;
if (target>num){
right = mid - 1;
}else if (target<num){
left = mid+1;
}else if (target == num){
return true;
}
}
return false;
}
- 时间复杂度:O(log n ),n为正整数num的最大值
- 空间复杂度为 O(1)