【二分查找专题】给出四种二分查找的模板
本问题对应课程链接:剑指offer刷题第五期
本次打卡的任务很简单,就是给出四种变形二分查找的模版代码,并且给出了对应的方法名字。
比如对于一个有序数组
arr = [1,2,3,3,3,4,5,5,7],target = 3,那么
1.寻找第一个大于 target 的元素的下标,本案例中4 就是第一个大于 target 的元素 ,下标 = 5。
对应方法名格式为
int upper(int[] arr, int target){
//如果都不存在,则返回-1
}
2.如果数组中存在元素等于 target,则返回最后一个等于target 的元素下标,如果不存在,则返回第一个大于 target 的元素下标。本案例中最后一个等于target的下标 = 4。
对应方法名
int floor_upper(int[] arr, int target){
//如果都不存在,则返回-1
}
3.寻找最后一个小于 target 的元素的下标,本案例中 2 则是最后一个小于 target 的,下标 = 1.
对应方法名格式为
int lower(int[] arr, int target){
//如果都不存在,则返回-1
}
4.如果数组中存在元素等于 target,则返回第一个等于target 的下标,如果不存在,则返回最后一个小于 target 的元素的下标。本案例中第一个等于target的下标 = 2。
对应方法名格式为
int floor_lower(int[] arr, int target){
//如果都不存在,则返回-1
}
注意:大家给了模版之后,选择一个适合自己的模版,以后都用这个模版,忘了怎么办?这玩意的区别就是要么是大于,要么是大于等于,你如果记混了,可以随便找一组数据试一下,就能分辨出来了,我笔试时都这样干,,,
共以下 9 个回答
//给出四种变形二分查找的模板代码
//有序数组 arr = [1,2,3,3,3,4,5,5,7]
//target = 3
//给出四种变形二分查找的模板代码
//有序数组 arr = [1,2,3,3,3,4,5,5,7]
//target = 3
//寻找第一个大于target 的元素的下标,本案例中 4就是第一个大于target 的元素,下标 = 5
int upper(int[] arr, int target) {
//如果都不存在,则返回-1
if(arr[arr.length-1] <= target) return -1;
}
//如果数组中存在元素等于target,则返回最后一个等于target的元素的下标,
//如果不存在,则返回第一个大于target的元素的下标。本案例中最后一个等于target的下标 = 4
int floor_upper(int[] arr, int target) {
//如果都不存在,则返回-1
if(arr[arr.length-1] < target) return -1;
if(arr[arr.length-1] target) return arr.length-1;
}
//寻找最后一个小于target的元素的下标,本案例中2则是最后一个小于target的,下标1
int lower(int[] arr, int target) {
//如果都不存在,则返回-1
if(arr[0] >= target) return -1;
}
//如果数组中存在元素等于target,则返回第一个等于target的下标,
//如果不存在,则返回最后一个小于target的元素的下标
int floor_lower(int[] arr, int target) {
//如果都不存在,则返回-1
if(arr[0] > target) return -1;
if(arr[0] target) return 0;
}
//简单记录一下寻找
//第一个大于target的元素的下标为什么向下取整(除法默认的)
//最后一个小于target的元素的下标为什么向上取整?mid = (l + r + 1) / 2;
第一个大于target的元素,第一次使用二分查找时,如果Mid对应的元素正好是最后一个等于target的元素,那么下一个寻找区间是[Mid+1, right]。区间里都是大于target的元素
即mid+1就是第一个大于target的元素。mid = (l + r) / 2可以取到左边界。
第一个大于target的元素 这个要求就是 左边界的值
最后一个小于target的元素的下标,第一次使用二分查找时,如果Mid对应的元素正好是第一个等于target的元素, 那么下一个寻找区间是[left, mid-1],区间里都是小于target的元素
即mid-1就是第一个大于target的元素。mid = (l + r) / 2永远只能取到左边界的值, 而mid = (l + r + 1) / 2才可以取到右边界。
最后一个小于target的元素 这个要求就是 右边界的值,所以需要向上取整
// 对有序数列进行二分查找,判断当前区间的时候两侧是闭区间的,意思是在当前的轮次当中,两侧的端点元素都加进考虑
// 寻找第一个大于target的元素下标
对于小于或小于等于类的问题,必须对mid取上限,以收缩左边界;对于大于或大于等于类的问题,直接对mid取下限即可,自动收缩右边界。
lower和upper注意偶数时中间点取偏左还是偏右