# 二分查找各种情况大总结

1.1 二分查找原始版–查找某个数的下标（任意一个）

public int binarySearch(int[] a, int n, int key){
//n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while(low <= high) {
mid = low + ((high-low) >> 1);
if(key == a[mid]) {
return mid;
} else if(key < a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}  

1.2 查找第一个大于等于某个数的下标

public int firstGreatOrEqual(int[] a, int n, int key){
//n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while(low <= high) {
mid = low + ((high-low) >> 1);
if(key <= a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low <= n ? low : -1;
}  

1、条件为key<=a[mid]，意思是key小于等于中间值，则往左半区域查找。如在 {1,2,2,2,4,8,10}查找2，第一步，low=0, high=6, 得mid=3, key <= a[3]，往下标{1,2,2}中继续查找。

2、终止前一步为: low=high，得mid = low，此时如果key <= a[mid]，则high会改变，而low指向当前元素，即为满足要求的元素。如果key > a[mid]，则low会改变，而low指向mid下一个元素。

3、如果key大于数组最后一个元素，low最后变为n+1，即没有元素大于key，需要返回 -1。

1.3 查找第一个大于某个数的下标

public int firstGreat(int[] a, int n, int key){
//n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while(low <= high) {
mid = low + ((high-low) >> 1);
if(key < a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low <= n ? low : -1;
}  

2.1 查找数组中某个数的位置的最小下标，没有返回-1

public int firstIndex(int[] a, int n, int key){
//n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while(low <= high) {
mid = low + ((high-low) >> 1);
if(key <= a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return (low <= n) && (a[low] == key) ? low : -1;
}  

2.2 查找数组中某个数的位置的最大下标，没有返回-1

public int lastIndex(int[] a, int n, int key){
//n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while(low <= high) {
mid = low + ((high-low) >> 1);
if(key < a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return (low - 1 >= 0 && (a[low - 1] == key))? low - 1: -1;
}  

2.3 查找数组中小于某个数的最大下标，没有返回-1

public int firstLess(int[] a, int n, int key) {
// n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while (low <= high) {
mid = low + ((high - low) >> 1);
if (key <= a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return (low - 1 >= 0) ? low - 1 : -1;
}  

2.4 查找数组中某个数的出现次数

public int getCount(int[] a, int n, int key) {
// n + 1 个数
int first = firstGreatOrEqual2(a, n, key);
int last = firstGreat2(a, n, key);
return last - first;
}

public int firstGreatOrEqual2(int[] a, int n, int key) {
// n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while (low <= high) {
mid = low + ((high - low) >> 1);
if (key <= a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}

public int firstGreat2(int[] a, int n, int key) {
// n + 1 个数
int low = 0;
int high = n;
int mid = 0;
while (low <= high) {
mid = low + ((high - low) >> 1);
if (key < a[mid]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return low;
}  

1、写此文章的目的是总结多种二分查找相似问题，网上的太多代码，边界条件杂乱且不容易理解。这里先总结出最基本的三种情况代码，再用三种情况的代码求解相似问题，理解复杂度降低。

2、一些问题，需要自己多总结，才能有理解深刻，才能写出最适合自己理解的代码。

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120