前端算法(48)

111 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

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

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

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

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

题目解析

思路一

取一个近似值 middle, 一般等于 x / 2,然后不断更新 middle,令 middle 等于 middle 和 x/middle 的平均数,结果和上一次差值小于某个值(我这里取的是 0.1)时,就可以认为这个 middle 是结果。

/**
 * @param {number} x
 * @return {number}
 */
var mySqrt = function(x) {
  if (x <= 1) return x
  let prev = x / 2,
      current = NTMethod(x, prev)
  while(prev - current > 0.1) { 
    prev = current
    current = NTMethod(x, prev)
  }
  return Math.floor(current)
};
function NTMethod(x, middle) {
  return (middle + x / middle) / 2
}

思路二

我们判断一下平方根是不是自己,如果是自己就返回,0和1的平方根就是自己,然后再定义一个中位数,如果中位数西小于当前目标值,则向左缩小范围,否则向右缩小范围,在进行递归,继续在已经缩小范围内里继续查找,直到值小于1时结束

/**
 * @param {number} x
 * @return {number}
 */
var mySqrt = function(x) {
            if (x == 0 || x == 1) return x
            var find = function (left, right, x) {
                if (right - left <= 1) return left;
                var mid = Math.floor((right + left) / 2)
               mid * mid > x?( right = mid ):(left = mid)
               return find(left, right, x)
            }
            return find(1, x, x)
};

思路三

由于结果只需要整数,所以直接 Math.floor 一下 mid,尽量避免浮点数预算,在判断 mid 的平方是否 <= x以及判断 mid + 1的平方是否 >x

/**
 * @param {number} x
 * @return {number}
 */
var mySqrt = function(x) {
    if (x === 1 || x === 0) {
        return x
    }
    let low = 1, high = x, mid = Math.floor(low + (high - low)/2)
    while (!(x - Math.pow(mid, 2) >= 0 && x - Math.pow(mid + 1, 2) < 0)) {
        if (Math.pow(mid, 2) < x) {
            low = mid
        } else {
            high = mid
        }
        mid = Math.floor(low + (high - low)/2)
    }
    return mid
};