「前端刷题」69. Sqrt(x)

182 阅读1分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」。

题目

链接:

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

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

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

 

示例 1:

输入: x = 4 输出: 2

示例 2:

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

 

提示:

  • 0 <= x <= 231 - 1

解题思路

红蓝划分法

var mySqrt = function(x) {
     if(x === 0 || x === 1) return x
     let l = -1
     let r = x
     while( l+1 !== r){
         let mid = Math.floor((l+r)/2)
         if(mid * mid <= x){
             l = mid
         }else{
             r = mid
         }
     }
     return l
 };

牛顿迭代

image.png

如何通俗易懂地讲解牛顿迭代法?

五次及以上多项式方程没有根式解(就是没有像二次方程那样的万能公式),这个是被伽罗瓦用群论做出的最著名的结论。

但是,没有王屠夫难道非得吃带毛猪?工作生活中还是有诸多求解高次方程的真实需求(比如行星的轨道计算,往往就是涉及到很复杂的高次方程),这日子可怎么过下去啊?

没有根式解不意味着方程解不出来,数学家也提供了很多方法,牛顿迭代法就是其中一种。

对于毕业好几年,有点费脑筋

var mySqrt = function(x) {
     let n = x
     while( n * n > x){
         n = Math.floor((n+x/n)/2)
     }
     return n
};

二分查找,逼近目标值

  • 首先是边界情况: 0、1的平方根分别是0、1
  • 剩下就是 x>=2 的情况:
    • 左右指针指向左右边界
    • 求出中位数 mid
    • 如果 mid 的平方正好等于 x,则返回 mid
    • 如果 mid 的平方小于 x,说明平方根落在 mid 和 right 之间,让 left=mid
    • 如果 mid 的平方大于 x,说明平方根落在 left 和 mid 之间,让 right=mid
    • 退出循环的条件是左右指针相邻了。它们俩中有一个是平方根。再判断一下就好。

代码

const mySqrt = (x) => {
  if (x < 2) return x;
  let left = 1;
  let right = x >>> 1;        // 除以2并取整,缩小一下遍历的范围
  while (left + 1 < right) {  // 退出循环时,它们相邻
    let mid = (left + right) >>> 1;
    if (mid == x / mid) {
      return mid;
    } else if (mid < x / mid) {
      left = mid;
    } else {
      right = mid;
    }
  }
  return right > x / right ? left : right;
};