LeetCode.69 x 的平方根| 8月更文挑战

486 阅读2分钟

这是我参与8月更文挑战的第2天,活动详情查看:8月更文挑战

题目描述:

原题地址

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例一

输入: 4
输出: 2

示例二

输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 
     由于返回类型是整数,小数部分将被舍去。

思路分析

二分查找

这个找数的题目是一个典型的二分查找法的应用场景。

之前在 LeetCode - [35] 搜索插入位置 中我们已经用过二分法。这里再复习一下。

思路:

  • 寻找 x的平方根 的区间范围为 [left,right][left , right]
  • 在此区间内找解
    • 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

右边界的优化

正常的二分法我们右边界会取整个范围的右边界,但是此题中我们可以优化一下

  1. x > 2 的时候,他的平方根一定小于 x / 2
  2. x = 1 的时候,x / 2 = 0,为兼容这个case,右边界可以 +1
  3. 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)