LeetCode69、x 的平方根

98 阅读2分钟

LeetCode 系列记录我学习算法的过程。

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情

题目

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

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

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5

示例:

输入: x = 4
输出: 2


输入: x = 8
输出: 2
解释: 8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

提示

  • 0 <= x <= 231 12^{31 - 1}

思路

根据题意可知求 x 的平方根,且只保留整数部分,即 i * i <= x(i + 1) * (i + 1) > x

那就很容易了,直接暴力循环从 0 开始,当 i * i > x 时结束循环,返回 i - 1 即可

代码实现

/**
 * @param {number} x
 * @return {number}
 */
var mySqrt = function(x) {
    let i = 0
    // 当 i * i > x 时结束循环
    while(i * i <= x) i++
    // 返回 i - 1
    return i - 1
};

代码看起来是非常简洁,逻辑也很清晰,但是就是效率太低了,执行耗时非常不理想

image.png

优化

上面这种是最简单的解法,也是最笨的,还可以使用二分法来提高效率,每次循环可以排除一半的数字,比之前的暴力循环法更高效:

  • 首先可以把特殊情况处理,01 的平方根都是自身
  • 定义 leftright 为左右指针
  • leftright 相差 1 时,结束循环返回 left
  • 每次循环取中间值 mid,当 mid 的平方等于 x 时返回 mid
  • 当小于 x 时,赋值 leftmid
  • 反之赋值 rightmid
var mySqrt = function (x) {
    // 当 x 为 0 或 1 时,直接返回 x
    if (x === 0 || x === 1) return x
    // 左指针
    let left = 0
    // 右指针
    let right = x

    // 相差 1 时结束循环
    while (left < right - 1) {
        // 取中间值 mid
        let mid = Math.floor((left + right) / 2)
        // 平方值为 x 则返回 mid
        if (mid * mid === x) {
            return mid
        }
         // 小于 x 则 left 赋值为 mid,反之赋值 right 为 mid
        if (mid * mid < x) {
            left = mid
        } else {
            right = mid
        }
    }

    return left
};

image.png