字节笔试题 leetcode 69. x 的平方根

2021-05-28 14:02:50 浏览数 (2)

题目

题目要求非负整数 x 的平方根,相当于求函数 y = √x 中 y 的值,函数 y = √x 图像如下:

从上图中,可以看出函数是单调递增的,满足二分查找的条件(区间是有序的),所以可以考虑用二分查找去做。

解题细节

1、由于当 x 为非负整数时,其平分根一定在区间 [1, x/2 1] 内,所以为了缩小查找的范围,二分的左右边界分别取 left = 1 和 right = x / 2 1,而不分别取 0 和 x;

2、为了防止在查找过程中比较 mid * mid 和 x 中前者值太大,超出整型范围而溢出,取 mid 与 x / mid 进行比较(mid 为 解题细节 1 中 的 left 和 right 的和的平均值,故不会等于 0)。

Show me the Code

代码语言:javascript复制
// C 语言版本
int mySqrt(int x){
    int left = 1, right = x / 2   1;
    while (left <= right) {
        /* 防止溢出 */
        int mid = left   ((right - left) >> 1);  
        /* mid 大于 √x ,在 mid 前半区间查找 */
        if (mid > x / mid) {                     
            right = mid - 1;
        /* mid 小于 √x ,在 mid 后半区间查找 */
        } else if (mid < x / mid) {              
            left = mid   1;
        /* mid 等于 √x ,查找到直接返回 */
        } else if (mid == x / mid) {                                 
            return mid;
        }
    }

    return right;
}
# python3 版本
class Solution:
    def mySqrt(self, x: int) -> int:
        l, r = 1, x/2   1
        while l <= r:
            m = (l   r) // 2
            if m > x / m:
                r = m - 1
            elif m < x / m:
                l = m   1
            else:
                return int(m)
        return int(r)

说明

  1. right = x / 2 1,而不是 right = x / 2,因为当 x = 1 时,如果 right 取 x / 2 的话,由于 x/2 = 0,此时 left = 1 大于 right,直接循环跳出,导致 x 的平方根为 0 而不是 1 出错;
  2. 最后是 return right 还是 return left,可以通过调试得出,循环退出的条件是 left = right 1,当 x = 8 的时候,题目要求返回的是 2 ,如果最后是 return left 的话,返回的结果是 3 ,所以返回的是 right 。

0 人点赞