题目:
由于返回类型是整数,结果只保留整数部分 ,小数部分将被舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5)
或者 x ** 0.5
。
示例 1:
输入:x = 4
输出:2
示例 2:
输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
题目分析
这道题显然是在考察我们对循环结构的理解程度。
我们这里选择二分查找算法。
具体为:
建立3个变量:
- left —— 最左值
- right —— 最右值
- root —— 测试值
循环方法:
- root = left + (right - left) / 2
- root < x ---> 改root为当前root到right的中间值
- root > x ---> 改root为当前root到left的中间值
- 判断root与上一个root直接是否有整数,若没有,则直接返回 root - 1
- root = x ---> 直接输出结果
代码实现
import java.util.Scanner;
//题目:不用库函数去寻找一个数算数平方根的整数解
//eg:9的算数平方根为3 ---------- 我们输出3
// 8的算数平方根为2.828... --- 我们输出2
public class LoopTest {
public static void main(String[] agrs) {
int x = 0;
int root = 0;
//录入x
System.out.println("请输入一个正整数:");
Scanner sc = new Scanner(System.in);
x = sc.nextInt();
//调用求整数平方根class
ExtractRoot find = new ExtractRoot();
root = find.ExtractRootMethod(x);
//输出结果
System.out.println(x + "的去小数算数平方根为:" + root);
sc.close();
}
}
class ExtractRoot{
public int ExtractRootMethod(int x) {
//合法性判断
if(x < 0>{
return -1;
}
//特殊处理0和1
if( x == 1 || x == 0){
return x;
}
long root = 0;
long left = 1;
long right = x;
while(left <= right) {
//二分查找
//1.如果小于x -> 改root为当前root到right的中间值
//2.如果大于x -> 改root为当前root到left的中间值。
//若当前root与上一个root之间无整数,则直接返回上一个root
//3.如果等于x -> 直接输出结果
root = left + (right - left) / 2;
//为了防止数值溢出,我们不使用常规的root * root == x
//而使用root == x / root
if(root < x / root) {
left = root + 1;
} else if (root > x / root) {
if (root - 1 < x / (root - 1)) {
//此时的root - 1 即为解
return (int)(root - 1);
} else {
right = root - 1;
}
} else if (root == x / root) {
return (int)root;
}
}
//此行代码实际上可能没有机会执行,只是为了确保所有路径都有返回值
//在大多数情况下,left 和 right 会收敛到同一个值.
//但是如果它们不收敛,我们应该返回 left
//因为它是最接近 x 的平方根的整数
return (int)left;
}
}