题目描述

✅ LCR 072. x 的平方根

image-20260929005633909

题意分析

对非负整数 x,返回平方根的整数部分,即最大的非负整数 k,满足 $k^2\le x$。完全平方数应返回精确的根,其余情况向下取整。

随着 k 增大,条件 $k^2\le x$ 只会从满足变为不满足,因此可以在整数答案范围内二分,寻找最后一个满足条件的值。题目给出 $0\le x\le 2^{31}-1$,实现还需要避免平方乘法溢出。

解法:二分整数平方根上界

核心思路

[!blue]

初始搜索区间取 [0,x]。零一定满足条件;对整数 x >= 1,平方根不超过 x,所以这个范围包含答案,x == 0 时也直接覆盖唯一答案。

对正数中点 mid,判定 $mid^2\le x$ 可以等价改写为 mid <= x/mid。整数除法向下取整不会改变这个判断:能放下至少 mid 个大小为 mid 的单位,正好意味着平方不超过 x。这样不必计算可能超出整数范围的乘积。

维护闭区间 [left,right] 包含答案,其中 left 是一个已知可行值。若中点满足条件,答案可能就是它,也可能更大,令 left = mid;否则中点及其右侧都过大,令 right = mid-1。

因为可行分支保留 mid 作为左端,中点必须向上取整。只要 left < right,就有 left < mid <= right,两种更新都能缩小范围。并且 left >= 0,进入循环后的中点一定大于零,所以除法不会遇到零分母。

Java 用 (left+right+1) >>> 1 取上中点:在本题非负 32 位范围内,无符号右移按加和的位模式得到正确结果,不能换成有符号右移。Go 用等价的 right-(right-left)/2,既向上取整,又避免先计算 right-left+1 在 32 位整数上界溢出。

解题步骤

  1. 设置 left = 0、right = x。
  2. 当左右边界不同,计算上中点并判断 mid <= x/mid。
  3. 可行就把左端移到中点,不可行就把右端移到中点前一位。
  4. 区间只剩一个整数时返回 left,它就是最大的可行候选。

x == 0 时循环不执行;x == 1 时唯一需要检查的正数中点为一。完全平方数的根满足带等号的判定,会被保留下来。

代码实现

class Solution {
    public int mySqrt(int x) {
        int left = 0;
        int right = x;

        while (left < right) {
            int mid = (left + right + 1) >>> 1;

            if (mid <= x / mid) {
                left = mid;
            } else {
                right = mid - 1;
            }
        }

        return left;
    }
}
func mySqrt(x int) int {
    left, right := 0, x
    for left < right {
        mid := right - (right-left)/2
        if mid <= x/mid {
            left = mid
        } else {
            right = mid - 1
        }
    }
    return left
}

复杂度分析

  • 时间复杂度:$O(\log(x+1))$,每轮缩小约一半候选,题目范围内最多约 $31$ 轮。
  • 空间复杂度:$O(1)$,只维护几个整数下标。

关键点总结

[!green]

  • 向下取整的平方根是最后一个平方不超过 x 的整数,搜索目标仍是离散边界。
  • left = mid 必须配上中点,使两个候选时仍能推进。
  • 除法判定避免平方溢出;循环不变量同时保证分母为正。

易错点总结

[!yellow]

  • 直接用普通整数计算 mid*mid,可能在比较之前就已经溢出。
  • 使用下中点却仍更新 left = mid,可能卡在两个候选之间。
  • 不可行时仍保留中点,或可行时把中点排除,都会破坏当前边界含义。
  • 只处理正数而漏掉 x == 0,或把完全平方数根上的等号排除。

相似题目

题目 难度 关联与区别
367. 有效的完全平方数 简单 同样比较平方与目标,原题判断是否恰为完全平方,本题返回平方根的整数下界。
441. 排列硬币 简单 同样对单调增长的数值表达式二分,原题找满足三角数不超过n的最大层数。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/60776124
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!