# 三种基本版本：

## 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、一些问题，需要自己多总结，才能有理解深刻，才能写出最适合自己理解的代码。

#### 二分查找过程、比较次数分析、java实现

2016-09-12 14:26:26

#### 二分查找算法流程图流程图举例

2009年05月26日 55KB 下载

#### 二分题目最全总结（持续更新）

2016-10-31 15:03:32

#### 二分查找（Binary Search）常见问题解决方法总结

2017-07-17 16:07:00

#### 二分查找算法（递归与非递归两种方式）

2014-04-27 15:44:26

#### 浅谈-二分查找

2016-10-07 20:54:13

#### 二分查找

2016-07-22 11:21:47

#### 折半查找

2017-11-01 14:44:14

#### 2种二分查找及2种优化方式

2015-09-06 22:13:26

#### 二分查找（源码）

2017-05-08 21:03:24