题目
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
示例
代码
这个是首先对x数,进行处理,
public class Solution {
public int MySqrt(int x) {
if (x==0)
{
return 0;
}
int low = 1, high = x/2;
int mid = 0;
while (low<high)
{
mid = (low + high+1) / 2;
if (mid<=x/mid)
{
low = mid;
}
else
{
high = mid-1;
}
}
return low;
}
}
再来一种后处理的
public int MySqrt(int x)
{
int low = 1, high = x/2;
while (low < high)
{
int mid = low + (high - low + 1) / 2;
if (mid < x / mid)
{
low = mid;
}
else if (mid > x / mid)
{
high = mid - 1;
}
else
return mid;
}
//if (low <= x)
//{
// return low;
//}
//else
// return low - 1;
return low <= x ? low : low - 1;
}
直接先二分查找,在最后判断结果,
low <= x,将x==0,和x == 1,等条件判断。
一般情况 low 一定小于或等于 x,一个数的算术平方根一定小于或等于这个数。
low - 1,处理的就是x = 0,而low = 1,的情况。
分析
part1: c++可以直接调用sqrt方法,进行算术平方根的取值。
part2:就是上边这个方法,使用二分查找来减少时间复杂度。
high = x/2;因为算术平方根结果一般小于x的一半。
使用x/mid是防止溢出,也可以使用long类型来接受mid*mid的结果。
一个重点问题:mid向上取整的问题。
其实具体为什么向上取整我也不知道,就是知道,不+1会陷入死循环,向上取,向下取,试一试。向下取满足不了题目要求,实现不了提取最终low。
当low = mid,的时候,就要考虑向上取整,打印一下就知道了。会死循环,所以需要向上取整。只要有low = mid的情况,就要考虑向上取整 |
一定要退出循环,不然跑完的结果就是时间超时。
这个和之前的二分查找还有点区别,之前的直接(low + high) / 2,这个题的mid需要向上取整一下。
向上取整、向下取整还是不用处理的这个问题主要看题目分析。
需要向上取,扩容。避免死循环。
遍历几个试一试。
看看具体数就知道向上取还是向下取了。
一定要注意退出循环的条件。