这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战
题目描述:
实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例一
输入: 4
输出: 2
示例二
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
思路分析
二分查找
这个找数的题目是一个典型的二分查找法的应用场景。
之前在 LeetCode - [35] 搜索插入位置 中我们已经用过二分法。这里再复习一下。
思路:
- 寻找
x的平方根的区间范围为 - 在此区间内找解
-
当
left < right的时候var middle = (left + right) /2
var square = middle * middle
注意这个地方
square有可能溢出,所以我们可以转long-
如果 square > x,则 right = middle -1
-
如果 square < x,则 left = middle + 1
-
如果 square == x,即平方根为 middle
-
-
右边界的优化
正常的二分法我们右边界会取整个范围的右边界,但是此题中我们可以优化一下
- 当
x > 2的时候,他的平方根一定小于x / 2 - 当
x = 1的时候,x / 2 = 0,为兼容这个case,右边界可以+1 - 当
x = 0的时候,x / 2 = 0,这个case下x / 2可以满足
综上 我们右边界可以优化为 x / 2 + 1
AC代码
class Solution {
fun mySqrt(x: Int): Int {
var left = 0L
var right = (x ushr 1).toLong() + 1
val target = x.toLong()
while (left <= right) {
val middle = (left + right) ushr 1
val square: Long = middle * middle
when {
square == target -> return middle.toInt()
square < target -> left = middle + 1
else -> right = middle - 1
}
}
return right.toInt()
}
}
牛顿法
关于牛顿法,详见 官方解题
袖珍计算器算法
这个解法是看 官方解题 中的第一个解法,说实话,这个解法我不明白为什么不直接用 sqrt(), 可能考察到一点数学知识吧,对数的转换等。
这里也不做详细介绍,感兴趣的看官解吧。
总结
这题对我来说主要还是考察二分法吧,至于那个牛顿法,后面如果再接触到,再统一学习下。
看了不少题解,二分法还是有好几个模板的,目前还没有掌握那么熟透,还要多多练习。
参考
二分查找(Java) - x 的平方根 - 力扣(LeetCode) (leetcode-cn.com)
二分法 (Java And Kotlin) - x 的平方根 - 力扣(LeetCode) (leetcode-cn.com)