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;
};