题
题解
package 力扣;
import java.util.Scanner;
/**
* @author 邓雪松 (づ ̄ 3 ̄)づ)
* @create 2021-11-04-11-48
*/
public class 完全平方数 {
//方法一:使用内置的库函数,
//根据完全平方数的性质,我们只需要直接判断num的平方根x是否为整数即可。
public static boolean isPerfectSquare(int num){
int x = (int)Math.sqrt(num);
return x * x == num;
}
//方法二:暴力
//思路和算法
//如果num为完全平方数,那么一定存在正整数x满足x*x=num。于是我们可以从1开始,从小到大
//遍历所有的正整数,寻找是否存在满足x*x=num的正整数x。在遍历中,如果出现正整数x使x*x>num,
//那么更大的正整数也不可能满足x*x=num,不需要继续遍历了
//主要还是没想到大于就停止遍历的想法
public static boolean isPerfectSquare2(int num){
long x = 1,square = 1;//square是平方的意思
while(square <= num) {//确保平方的数是小于等于num的,不然的话就就证明num不是完全平方数
if(square == num){//如果平方数等于num则表示x*x==num 代表num是完全平方数
return true;
}
++x;
square = x * x;
}
return false;//大于了就直接返回false即可
}
//上面的时间复杂度:O(根号n),其中n为正整数num的最大值。我们最多需要遍历(根号n+1)个正整数
//上面的空间复杂度:O(1)
//方法三:二分查找
//思路和算法
//考虑使用二分查找来优化方法二中的搜索过程。因为num是正整数,所以若正整数x满足x*x=num
//则x一定满足1<=x<=num.于是我们可以将1和num作为二分查找搜索区间的初始边界。
//细节:
//因为我们在移动左侧边界left和右侧边界right时,新的搜索区间都不会包含[被检查的下标]mid,所以搜索区间的边界始终
//是我们没有检查过的。因此,当left=right时,我们仍需要检查mid = (left + right)/2
public static boolean isPerfectSquare3(int num){
int left = 0,right = num;
while(left<=right){
int mid = (right-left)/2+left;//注意这里+left了
long square = (long)mid * mid;//square还是mid的平方数
if(square<num){//平方数<num,则证明mid在右边
left = mid + 1;//让左指针挪到mid的右侧
}else if(square > num){//如果square>num,则代表mid在左侧
right = mid -1;//移动右指针
}else{
return true;//运行这里则代表mid*mid=nun 代表找到了
}
}
return false;//否则就代表没有找到
}
//复杂度分析
//时间复杂度:O(log n),其中n为正整数num的最大值
//空间复杂度:O(1)
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("输入:num = ");
int num = sc.nextInt();
boolean b = isPerfectSquare3(num);
System.out.println(b);
}
}