🚩传送门:牛客题目
题目
给定一个非负整数 ,计算并返回
的平方根,即实现
函数。
要求:
- 正数的平方根有两个,只输出其中的正数平方根。
- 如果平方根不是整数,输出只保留整数的部分,小数部分将被舍去。
示例 1:
输入: x = 4 输出: 2
示例 2:
输入: x = 8 输出: 2 解释: 8 的平方根是 2.82842…,由于小数部分将被舍去,所以返回 2
解题思路:二分法
对于非负整数 可以暴力搜索其正数平方根。从
开始,计算当前值
是否满足
- 成立就输出结果
- 不成立计算下一个值
++ 继续判断。
暴力解法的时间复杂度为 。
🚩这个过程其实可以使用 二分法优化 ,因为根据数学知识可知数字的平方根一定在区间
,取这个区间的中间值
,并判断
与
的大小关系。
- 若
,接着判断
。
- 如果满足 ,那么就是的平方根。
- 如果满足 ,则的平方根比大,继续搜索 `**[m + 1, n]**`。
- 若
,则说明
的平方根比
小,继续搜索
**[1, m - 1]**
。
解释代码
class Solution:
def mySqrt(self, x: int) -> int:
# 二分法
if x <= 1: #
return x
left = 0
right = x
while left <= right:
mid = (left+right)//2
if mid**2 <=x and (mid+1)**2 > x:
return mid
elif mid**2 < x: # 数值偏小,需要扩大
left = mid + 1
elif mid**2 > x: # 数值偏大,需要缩小
right = mid - 1
我的代码
class Solution {
public int mySqrt(int x) {
int left = 1;
int right = x;
while (left <= right) {
// 1.不可使用 (left+right)/2 原因:left+right 可能溢出int
int mid = left + ((right - left) >> 1);
// 2.不可使用 mid*mid 原因:mid*mid 可能溢出int
if (mid <= x / mid) {
if (mid + 1 > x / (mid + 1)) {
return mid;
}
left = mid + 1;
} else {
right = mid - 1;
}
}
return 0;
}
}