【JS每日一算法】🟩63.x 的平方根 (模拟法、二分法、牛顿迭代法)

273 阅读1分钟

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

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

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

提示:

  • 0 <= x <= 2^31 - 1

示例:

输入: x = 4
输出: 2

题解:

更多JS版本题解点击链接关注该仓库👀

/**
 * @description: 模拟法   TC:O(n)  SC:O(1)
 * @author: JunLiangWang
 * @param {*} x 给定非负整数 x
 * @return {*}
 */
function simulation(x){
    /**
     * 本方案使用模拟的方式,由于仅需要返回算术平方
     * 根整数部分,因此我们只需要从1开始逐步递增找
     * 到第一个其平方大于x的数,然后将该数-1即为答
     * 案
     */

    let root=1;
    // 从1开始逐步递增,找到第一个其平方大于x的数
    while(root*root<=x)root++;
    // 将该数-1即为答案
    return root-1;
}


/**
 * @description: 二分法  TC:O(logn)  SC:O(1)
 * @author: JunLiangWang
 * @param {*} x 给定非负整数 x
 * @return {*}
 */
function binary(x){
    /**
     * 本方案使用二分法,上述模拟法是通过将根逐步递增1来逼近答案的,
     * 因此存在优化空间,我们可以利用二分法不断在分割区间并做选择,
     * 使其2倍增或2倍减的方式逼近答案
     */

    // 初值化左指针为0
    let left=0,
    // 初值化右指针为x
    right=x,
    // 初始化中间值为0
    middle=0
    // 当左指针超出了右指针,遍历完成
    while(left<=right){
        // 计算中间值
        middle=Math.floor((left+right)/2);
        // 如果中间值的平方等于x,则为答案直接返回
        if(middle*middle==x)return middle;
        // 如果中间值的平方大于x,证明[middle,right]区间
        // 的平方都是大于x的,因此舍去该区间,并重置为
        // [left,middle-1]
        else if(middle*middle>x)right=middle-1
        // 如果中间值的平方小于x,证明[left,middle]区间
        // 的平方都是小于x的,因此舍去该区间,并重置为
        // [middle+1,right]
        else left=middle+1
    }
    // 当遍历完成都未找到平方与x相等的答案,
    // 此时返回left-1即可
    return left-1;
}

/**
 * @description: 牛顿迭代法   TC:O(logn)  SC:O(1)
 * @author: JunLiangWang
 * @param {*} x
 * @return {*}
 */
function newtonIteration(x){
    /**
     * 该方案使用牛顿迭代法,我们不断用(x,f(x))的切线来逼近x^2-a=0的根。
     * 根号a其实就是x^2-a=0的一个正实根,这个函数的导数为2x。也就是说
     * 函数上任意一点(x,f(x))的切线斜率为2x。那么,x-f(x)/(2x)就是一
     * 个比x更接近的近似值。法如f(x)=x^2-a得到x-(x^2-a)/(2x),也就是
     * (x+a/x)/2。
     *  */ 
    
    if (x == 0) {
        return 0;
    }

    let C = x, x0 = x;
    while (true) {
        let xi = 0.5 * (x0 + C / x0);
        if (Math.abs(x0 - xi) < 1e-7) {
            break;
        }
        x0 = xi;
    }
    return Math.floor(x0);
}

来源:力扣(LeetCode)