这是我参与更文挑战的第 12 天,活动详情查看: 更文挑战
有效数的完全平方数(367)
题目描述
给定一个 正整数 num
,编写一个函数,如果 num
是一个完全平方数,则返回 true
,否则返回 false
。
进阶:不要 使用任何内置的库函数,如 sqrt
。
示例 1:
输入:num = 16
输出:true
示例 1:
输入:num = 14
输出:false
提示
1 <= num <= 2^31 - 1
思路分析
求平方数的完全平方数,或者求某个数的平方根,很多时候都可以用二分法,默认数是从小到大,这样通过二分查找,查找的次数是很少的。
求题解还有一个需要注意的,就是可能遇到 int 数越界的问题,如果我们用 mid * mid 来判断是否等于目标值时,可能造成 mid * mid 越界,当然也可以用 long 进行处理,不过我们可以用 num/mid == mid && num % mid == 0
这个条件进行判断。
二分查找有一定的套路,首先定义 low 和 high,while 循环的判断条件一直是 low <= high,对于 low == high,必要的时候特殊处理,在 while 内部补充,返回值永远是 mid;low、high 的更新永远是 low = mid + 1 和 high = mid - 1;
对于非确定性的查找,使用前后探测法,来确定搜索区间。先处理命中情况,再处理左右半部分查找的情况。
代码展示
解法一:时间复杂度是,空间复杂度是。
public boolean isPerfectSquare(int num) { //如果需要k个小数,怎么解答???
if (num == 0 || num == 1){
return true;
}
int low = 0;
int high = (num + 1)/2; //5
while (low <= high){
int mid = low + (high - low)/2;
if (mid == 0){
return false;
}
if (num/mid == mid && num % mid == 0){ //num % mid == 0 很重要
return true;
} else if (num/mid > mid){ // 18 9
low = mid + 1;
} else {
high = mid - 1;
}
}
return false;
}
x 的平方根(69)
题目描述
实现 int sqrt(int x)
函数。计算并返回 x 的平方根,其中 x 是非负整数。由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
思路分析
这道题也是用二分法查找,解题思路和上面一样,这道题还需要截取小数部分,只取整数,需要注意个细节x / mid >= mid
,这里需要等号。
代码展示
解法一:时间复杂度是,空间复杂度是。
public int mySqrt(int x) { //5 2
if (x <= 1){
return x;
}
int low = 0;
int high = x/2+1; //3
while (low <= high){
int mid = low + (high - low)/2;
if (x / mid == mid && x % mid == 0){
return mid;
} else if (x / mid >= mid){ //这里很重要,还要加上等号 比如5/2 = 2
low = mid + 1;
if (x / low < low){
return mid;
}
} else {
high = mid - 1;
}
if (low == high){
if (low * high == x){
return low;
}
}
}
return -1;
}
总结
平方根和完全平方数都可以使用二分法解答,我们需要好好掌握二分法解法。二分查找有一定的套路,首先定义 low 和 high,while 循环的判断条件一直是 low <= high,对于 low == high,必要的时候特殊处理,在 while 内部补充,返回值永远是 mid;low、high 的更新永远是 low = mid + 1 和 high = mid - 1;
对于非确定性的查找,使用前后探测法,来确定搜索区间。先处理命中情况,再处理左右半部分查找的情况。