题目描述
求 x 的算术平方根,只保留整数部分(向下取整)。
x = 8
输出 = 2 (2²=4≤8,3²=9>8)
思路解析
k 越大 k² 越大,单调的。在 [0, x] 里二分 k:k² ≤ x 说明还能更大(记录答案,l 右移);k² > x 说明太大(r 左移)。
区间 [0,8] · mid=4:候选答案排成 0~8,mid=4:4²=16 > 8,太大,r 收到 3。
mid=1:区间 [0,3],mid=1:1²=1 ≤ 8,可行!记下 ans=1,试更大的,l=2。
mid=2:区间 [2,3],mid=2:2²=4 ≤ 8,更新 ans=2,继续试更大,l=3。
mid=3:区间 [3,3],mid=3:3²=9 > 8,太大,r=2。此时 l>r,循环结束。
答案 = ans = 2:最后记录的可行答案 ans = 2,就是 √8 的整数部分。
不必在数组里二分——只要「答案越大越满足/越不满足」,就能直接在答案范围里二分。爱吃香蕉、分割数组都是它。
参考代码(Python)
Python
1l, r, ans = 0, x, 0
2while l <= r:
3 mid = (l + r) // 2
4 if mid * mid <= x: # 可行,试更大
5 ans = mid; l = mid + 1
6 else: r = mid - 1 # 太大,缩小
7return ans复杂度分析
- 时间复杂度:O(log x) —— 每次砍一半
- 空间复杂度:O(1) —— 几个变量
套路模板
记住骨架:可行就记录 ans 并往大走、不可行往小走。求「最小可行」就反过来:可行往小走。
Python
1# 找「最大的满足 check 的值」
2l, r, ans = 最小, 最大, 默认
3while l <= r:
4 mid = (l + r) // 2
5 if check(mid): ans = mid; l = mid + 1 # 可行→记录并求更大
6 else: r = mid - 1
7return ans易错点
- ❌ mid*mid 溢出(其它语言) → ✅ Python 无忧;C++ 用 long 或比较 mid<=x/mid(大数相乘会溢出 int)
- ❌ 没记录 ans 直接返回 l/r → ✅ 可行时显式 ans=mid(边界返回容易差一,记录最稳)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。