问题描述:
Given a positive integer num, write a function which returns True if num is a perfect square else False.
Follow up: Do not use any built-in library function such as sqrt.
判断一个正整数是否是完全平方数,不允许用sqrt
思路:如果从1到num逐一排查,绝对会超时。往往这种情况会考虑用二叉搜索。
问题反思:我想到了用二叉搜索,但是忽略了越界问题,即mid*mid 会超出integer的最大范围。所以我们把left,right, mid全部设为long
代码如下:
class Solution {
public boolean isPerfectSquare(int num) {
if(num==1) return true;
long left=1;
long right=num;
while(left<right){
long mid=left+(right-left)/2;
//经测试(long)可以不写,java可以比较long和int
//long 和 int 比较时 int 自动转换成 long
if(mid*mid==(long)num){
return true;
}
//同理,(long)可以不写
else if(mid*mid>(long)num){
right=mid;
}
else{
left=mid+1;
}
}
return false;
}
}
时间复杂度: O(logn)
总结:
到目前为止已经做了好多道二叉搜索的题目了,下面总结一下一些容易错的点:
- left是从0开始,还是从1开始,还是从什么数开始,要根据题意灵活变化,同理right
- 求mid的方法用left+(right-left)/2可以保证不越界, 相反(left+right)/2 可能会在运算left+right时越界
- 因为我们求出的mid是“左偏中值”,比如1,2,3,4,我们的中间位置是2而不是3 。 所以如果我们需要取左半部分,right取mid(不减一);如果我们取右半部分,left取mid+1
- while循环的条件left<right, 是否含等号要根据具体题意, 但是我习惯不把等号写在循环条件中