69. x 的平方根

Posted by CodingWithAlice on June 29, 2021

69. x 的平方根

题目:

计算并返回 x 的平方根,其中 x 是非负整数。

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

总结:逻辑是一样的,找到区间 [i, i+1)

// 方法一:执行时长稍长,但内存占用小
function sqrt(x) {
    const mid = Math.ceil(x/2); // 优化点
    let i = 0;
    for(; i < mid; i++) {
        if ((i * i <= x) && ((i + 1) * (i + 1) > x)) { // 注意这里要给 = 号,否则会遗漏
            return i;
        }
    }
    return i
};
// 方法二 开区间 (left, right):执行时间短,但内存占用大点儿
function mySqrt3(x) {
    let left = 0, right = Math.min(x + 1, 46341);
    while (left + 1 < right) {
        // 循环不变量:left^2 <= x && right^2 > x
        let m = Math.floor((left + right) / 2);
        if (m * m <= x) {
            left = m;
        } else {
            right = m;
        }
    }
    // 循环结束时得到 left+1 == right,此时 left^2 <= x 且 right^2 > x
    return left; // 所以 left 最大的满足 m^2 <= x 的数
};

解答:

  • 方法一:遍历

平方根 <= x/2,取 x 的一半(取向上靠近的整数)

image-20210629083453119

时间复杂度:O(n),空间复杂度:xx

var mySqrt = function(x) {
    const mid = Math.ceil(x/2);
    let i = 0;
    for(; i < mid; i++) {
        // 注意这里要给 = 号,否则会遗漏
        if ( (i * i <= x) && ((i + 1) * (i + 1) > x)) {
            return i;
        }
    }
    return i
};
  • 方法二:二分法

image-20210629235752292

时间复杂度:O(logx) - 每一次搜索的区间大小为原来的 1/2,空间复杂度:O(1)

逻辑:将要查找的值划分在区间 [left, right) 中,通过两者的中间值 midx 的比较来判断求解的结果在哪个区间,直到最后找到对应结果

let mySqrt = (x) => {
    if (x === 0) {
        return 0;
    }
    let left = 0, right = x;
    let mid = Math.ceil(x / 2);
    while(left < right) {
        // 不用乘法,防止溢出
        if (x / mid === mid) {
            return mid;
        }
        if (x / mid < mid) {
            // 注意 ⚠️ :通过判断条件已知 mid^2 大于 x
            right = mid - 1;
        } else {
            left = mid;
        }
        mid = Math.ceil((left + right) / 2);
    }
    return left
}