参考:
https://blog.csdn.net/zxzxzx0119/article/details/82670761
共7中情况:(假设要找的元素为key)
(1)普通二分;
(2)第一个等于key的;(3)第一个大于等于key的;(4)第一个大于key的
(5)最后一个等于key的;(6)最后一个大于等于key的;(5)最后一个大于key的;
代码通用部分:
(1)while循环条件都是L<=R;
(2)判断条件里都是arr[mid]和key进行比较,且arr[mid]在前
不同部分口诀:一大二小,一左二右,等于要判断
解释:
(1)一大二小(其实要求是什么判断条件就写成什么,比如要求第一个大于等于,就写>=, 最后一个小于等于就写<=)
找第一个。。。的(即2,3,4三种情况),判断条件都是arr[mid]>key或者arr[mid]>=key;找最后一个。。。的(即5,6,7三种情况),判断条件都是arr[mid]<key或者arr[mid]<=key
当要求中含有等于要求时(即等于key, 大于等于key,小于等于key),判断条件加上等于号(>= 或者<=),否则(大于key,小于key)判断条件不加等号(>或者<)
(2)一左二右
找第一个。。。的(即2,3,4三种情况),返回的都是R;找最后一个。。。的(即5,6,7三种情况),返回的都是L。
(3)等于要判断
如果是找第一个等于key或者最后一个等于key的还需要在while结束后加上判断找到的是否合法的条件。
第一个等于key:
由于返回的是L,需要对L进行判断
L<arr.size() && arr[L]==key
最后一个等于key的:
由于返回的是R,需要对R进行判断
R>=0 && arr[R]==key
————————————————————————————————————
以下是代码:
(1)普通二分
int L = 0,R = arr.length - 1; //在[L,R]范围内寻找key
int mid;
while( L <= R){
mid = L + (R - L) / 2;
if(arr[mid] == key)
return mid;
if(arr[mid] > key)
R = mid - 1;// key 在 [L,mid-1]内
else
L = mid + 1;
}
return -1;
(2)第一个等于key的
int L = 0, R = arr.length - 1;
int mid;
while( L <= R){
mid = L + (R - L)/2;
if(arr[mid] >= key) //一大,要求有等于加等号
R = mid - 1;
else
L = mid + 1;
}
if(L < arr.length && arr[L] == key) //等于要判断
return L; //一左
return -1;
(3)第一个大于等于key的
int L = 0, R = arr.length - 1;
int mid;
while( L <= R){
mid = L + (R - L) / 2;
if(arr[mid] >= key) //一大,要求有等于加等号
R = mid - 1;
else
L = mid + 1;
}
return L; //不是等于不判断,一左
(4)第一个大于key的
int L = 0,R = arr.length - 1;
int mid;
while(L <= R){
mid = L + (R - L) / 2;
if(arr[mid] > key) //一大,不要求有等于不加等号
R = mid - 1;
else
L = mid + 1;
}
return L; //不是等于不判断,一左
(5)最后一个等于key的
int L = 0, R = arr.length - 1;
int mid;
while( L <= R){
mid = L + (R - L)/2;
if(arr[mid] <= key) //二小,要求等于要加等号
L = mid + 1;
else
R = mid - 1;
}
if(R >= 0 && arr[R] == key) //是等于要判断
return R; //二右
return -1;
(6)最后一个小于等于key的
int L = 0, R = arr.length - 1;
int mid;
while( L <= R){
mid = L + (R - L) / 2;
if(arr[mid] <= key) //二小,要求等于要加等号
L = mid + 1;
else
R = mid - 1;
}
return R; //不是等于不用判断,二右
(7)最后一个小于key的
int L = 0, R = arr.length - 1;
int mid;
while(L <= R){
mid = L + (R - L) / 2;
if(arr[mid] < key) //二小,不要求等于不要加等号
L = mid + 1;
else
R = mid - 1;
}
return R; //不是等于不用判断,二右