LeetCode系列记录我学习算法的过程。
携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
题目
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
示例:
输入: x = 4
输出: 2
输入: x = 8
输出: 2
解释: 8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
提示
- 0 <= x <=
思路
根据题意可知求 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
};
代码看起来是非常简洁,逻辑也很清晰,但是就是效率太低了,执行耗时非常不理想
优化
上面这种是最简单的解法,也是最笨的,还可以使用二分法来提高效率,每次循环可以排除一半的数字,比之前的暴力循环法更高效:
- 首先可以把特殊情况处理,
0和1的平方根都是自身 - 定义
left和right为左右指针 - 当
left与right相差1时,结束循环返回left - 每次循环取中间值
mid,当mid的平方等于x时返回mid - 当小于
x时,赋值left为mid - 反之赋值
right为mid
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
};