小故事
小乔在[0, 1, 3, 4, 6, 8, 9 ,10]的八个数字中想了一个,最多给你三次机会,她会告诉你:你猜的数字是大了还是小了,你能猜到吗?
小乔可能长这样:
情景一:
LOOK:正着猜两个吧,0 和 1
小乔:不对呦
情景二:
LOOK:倒着猜两个吧,8 和 9
小乔:不对呦,游戏结束
情景三:
LOOK:瞎猜吧,3 和 4 (当然幸运的你可能会命中 6 哦)
小乔:不对呦,游戏结束
瞎猜不靠谱,这怎么办?
带着这个好奇心,我们请出今天的主角——
二分查找
二分查找(也称折半查找),用来描述在有序集合中搜索目标值的过程,绝大部分在有序区间中搜索目标值的问题,都可以用二分查找来解决。
二分查找一般要确定四个参数:【下标一般是从0开始的,且要保证left <= right】
左边界 left
右边界 right
中间值 mid
目标值 target
题目解析
在小乔的问题中,我们知道左边界是 left = 0,右边界是 right = 7,中间值 mid = 3, 目标值 target = 6
LOOK:(将其分成两半)mid 对应的值是 4
小乔:小了
LOOK:(因为数列是有序递增的,如果 mid 小了,那么目标值就在 mid 之后,移动left,向右边搜
转移战线:left = mid + 1 = 4, right = 7; mid = 5 )mid 对应的值是 8
小乔:大了
LOOK:(再更新搜索范围,如果 mid 小了,那么目标值就在 mid 之前,移动 right, 向左边搜
转移战线:left = 4, right = mid - 1 = 4, mid = 4)mid 对应的值是6
小乔:恭喜你!猜对啦!!
代码实现
public class test{
public static void main(String[] args) {
int[] nums = {0, 1, 3, 4, 6, 8, 9, 10};//给出的数字
int target = 6;//目标值
int len = nums.length;//得到数组的长度
int left = 0, right = len - 1;//得到两个指针
while(left <= right) {//循环条件
int mid = left + (right - left) / 2;//中间值
if(nums[mid] == target) {//找到目标值
System.out.println(nums[mid]);//输出
break;//停止搜索
}else if(nums[mid] > target) {//找得到的值比目标值大
right = mid - 1;//向左边搜,右边界左移
}else {//找到的值比目标值小
left = mid + 1;//向右边搜,左边界右移
}
}
}
}
结果
6