目录
- [mid 中点问题](#mid 中点问题)
mid 中点问题
两个 mid 写法
1️⃣ 1,标准中点(向下取整)
java
// 标准中点(向下取整)
int mid = l + (r - l) / 2;
// 等价于
mid = floor((l + r) / 2);
// 偏左中点(left middle)
2️⃣ 2,偏右中点(向上取整)
java
// 偏右中点(向上取整)
int mid = l + (r - l) / 2 + 1;
// 等价于
mid = ceil((l + r) / 2);
// 偏右中点(right middle)
为什么不用 (l + r) / 2?
(l + r) / 2 ❌可能整数溢出
当 l,r 接近 Integer.MAX_VALUE:
l + r 会溢出变负数
所以统一写:
l + (r - l) / 2
偏左 mid vs 偏右 mid 的本质区别
👉 区间只有两个元素时:
偏左中点是left
偏右中点是right
在二分模板中
java
// 模板 A:找左边界(更新 r)
while (l < r) {
int mid = l + (r - l) / 2; // 偏左
if (check(mid)) r = mid;
else l = mid + 1;
}
// 因为这里是 r = mid → mid 必须偏左,否则 r 不动,会死循环
// 模板 B:找右边界(更新 l)
while (l < r) {
int mid = l + (r - l) / 2 + 1; // 偏右
if (check(mid)) l = mid;
else r = mid - 1;
}
// 因为这里是 l = mid → mid 必须偏右,否则 l 不动,会死循环
二分模板总结
模板 1:找第一个满足条件的位置(lower bound)
👉 左边界
java
while (l < r) {
int mid = l + (r - l) / 2;
if (check(mid)) r = mid;
else l = mid + 1;
}
模板 2:找最后一个满足条件的位置(upper bound)
👉 右边界
java
while (l < r) {
int mid = l + (r - l) / 2 + 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
LeetCode 高频场景对照表
题型 mid 写法
找最小满足 偏左 mid
找最大满足 偏右 mid
普通二分 偏左 mid
分治 merge sort 偏左 mid
快速选择 偏左 mid
为什么分治一般用偏左 mid?
比如 merge sort:
mid = (l + r) / 2
left = [l, mid]
right = [mid+1, r]
必须保证区间不重叠、不丢元素。
相关面试问题
❓ 为什么要 +1?
👉 防止 l 不移动导致死循环
👉 用于找"右边界"
❓ 偏左 vs 偏右什么时候用?
👉 取决于你更新的是 l 还是 r
终极口诀
找左边界 → 偏左 mid
找右边界 → 偏右 mid
防死循环 → l = mid 时必须 +1