为什么有一些二分查找取 mid 的时候要加 1
Posted liweiwei1419
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么有一些二分查找取 mid 的时候要加 1相关的知识,希望对你有一定的参考价值。
为什么有一些二分查找取 mid 的时候要加 1
以「力扣」第 69 题:x 的平方根为例。
题目描述:实现 int sqrt(int x)
函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2
示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
数据范围:
0 <= x <= 2^31 - 1
这道问题的代码:
public class Solution {
public int mySqrt(int x) {
// 特殊值判断
if (x == 0) {
return 0;
}
if (x == 1) {
return 1;
}
int left = 1;
int right = x / 2;
// 在区间 [left..right] 查找目标元素
while (left < right) {
int mid = left + (right - left + 1) / 2;
// 注意:这里为了避免乘法溢出,改用除法
if (mid > x / mid) {
// 下一轮搜索区间是 [left..mid - 1]
right = mid - 1;
} else {
// 下一轮搜索区间是 [mid..right]
left = mid;
}
}
return left;
}
}
由于我们只是讲解 mid
为什么要 加
1
1
1,如何分析和解决这道问题,可以查看 题解。
对着错误的测试用例打印出变量 left
、right
和 mid
的值看一下就很清楚了。
public class Solution {
public int mySqrt(int x) {
// 特殊值判断
if (x == 0) {
return 0;
}
if (x == 1) {
return 1;
}
int left = 1;
int right = x / 2;
// 在区间 [left..right] 查找目标元素
while (left < right) {
// 取中间数 mid 下取整时
int mid = left + (right - left ) / 2;
// 调试语句开始
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("left = " + left + ", right = " + right + ", mid = " + mid);
// 调试语句结束
// 注意:这里为了避免乘法溢出,改用除法
if (mid > x / mid) {
// 下一轮搜索区间是 [left..mid - 1]
right = mid - 1;
} else {
// 下一轮搜索区间是 [mid..right]
left = mid;
}
}
return left;
}
public static void main(String[] args) {
Solution solution = new Solution();
int x = 9;
int res = solution.mySqrt(x);
System.out.println(res);
}
}
控制台输出:
left = 1, right = 4, mid = 2
left = 2, right = 4, mid = 3
left = 3, right = 4, mid = 3
left = 3, right = 4, mid = 3
left = 3, right = 4, mid = 3
left = 3, right = 4, mid = 3
在区间只有
2
2
2 个数的时候,本题 if
、else
的逻辑区间的划分方式是:[left..mid - 1]
与 [mid..right]
。如果 mid
下取整,在区间只有
2
2
2 个数的时候有 mid
的值等于 left
,一旦进入分支 [mid..right]
区间不会再缩小,出现死循环。
解决办法:把取中间数的方式改成上取整。
最近正在 B 站讲解《算法不好玩》系列教程,地址,以新手视角讲解算法与数据结构,通俗易懂且不失严谨。公众号:算法不好玩。感谢大家支持!
以上是关于为什么有一些二分查找取 mid 的时候要加 1的主要内容,如果未能解决你的问题,请参考以下文章