求平方根

495 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

给定一个非负整数,计算并返回这个数的平方根

输入: x = 4
输出: 2

二、思路分析:

每次取一半的数和当前值做对比,如果比当前值大:下次的起始值不变,末尾值减1;如果比当前值小:下次的起始值加1,末尾值不变。

function mySqrt(num) {
  let left = 0
  let right = num
  while (left <= right) {
    const mid = Math.floor((right - left) / 2) + left
    console.log(mid)
    const square = mid * mid
    if (square < num) {
      left = mid + 1
    } else if (square > num) {
      right = mid - 1
    } else {
      return mid
    }
  }
  return -1
}

代码写完了,然后验证一下代码,输入4和9都可以正常的得到结果2和3,只要是完全平方根就没问题,但是输入3会有问题,因为代码中使用了 Math.floor 没有处理精度问题,所以3无法计算正确结果。

所以使用二分查找不一定能得到正确的结果,那我们可以使用其他办法来解决,使用递归的形式。

以计算3的平方根为例。最后求出3的平方根约等于1.732(保留小数点后三位)

function sqrt(num) {
  function sqrtWrapper(min, max) {
    let current = (min + max) / 2;
    let nextMin = min, nextMax = max;
    if (current * current > num) {
      nextMax = current;
    } else {
      nextMin = current;
    }
    if (min === nextMin && max === nextMax) {
      return current
    }
    else if (nextMax - nextMin < Number.EPSILON) {
      return current;
    } else {
      return sqrtWrapper(nextMin, nextMax);
    }
  }
  return sqrtWrapper(0, num);
}

注意由于浮点数计算问题需要阻止死循环的情况。

ES6 在Number对象上面,新增一个极小的常量Number.EPSILON。根据规格,它表示 1 与大于 1 的最小浮点数之间的差。

四、总结:

二分查找虽然无法正确计算任何数的平方根,只能处理完全平方根,所以我们可以使用二分查找判断一个数是否为完全平方根。

function isPerfectSquare(num) {
  let left = 0, right = num;
  while (left <= right) {
    const mid = Math.floor((right - left) / 2) + left;
    const square = mid * mid;
    if (square < num) {
      left = mid + 1;
    } else if (square > num) {
      right = mid - 1;
    } else {
      return true;
    }
  }
  return false;
};