二分查找就是将查找的键和子数组的中间键作比较,如果被查找的键小于中间键,就在左子数组继续查找;如果大于中间键,就在右子数组中查找,否则中间键就是要找的元素。
一、二分法查找
/** * 二分法查找,前提:数组必须先排好序 * * @param arrs * @param target * @return */
public static int binarySearch(int[] arrs, int target) {
int low = 0;
int high = arrs.length - 1;
int m = 0;
while(low <= high) {
m = (low + high) / 2;
if(arrs[m] == target) {
return m;
}
if(target < arrs[m]) {
high = m - 1;
}
if(target > arrs[m]) {
low = m + 1;
}
}
return -1;
}
二、二分法查找变种
关于二分查找,如果条件稍微变换一下,比如:数组之中的数据可能可以重复,要求返回匹配的数据的最小(或最大)的下标;更近一步, 需要找出数组中第一个大于key的元素(也就是最小的大于key的元素的)下标,等等。 这些,虽然只有一点点的变化,实现的时候确实要更加的细心。
二分查找的变种和二分查找原理一样,主要就是变换判断条件(也就是边界条件),还有就是注意判断返回值,是 low还是 high。
二分查找变种较多,不过它们的“套路”是一样的,基本步骤如下:
1. 根据要求判断出比较条件。
2. 判断出是返回low, 还是返回high。
题目中有“第一个/最左边“关键词就返回 low, 题目中有“最后一个/最右边”关键词就返回high。
1、查找第一个与target相等的元素
/** * 查找第一个与target相等的元素 * * @param arrs * @param target * @return */
public static int findFirstEqual(int[] arrs, int target) {
int low = 0;
int high = arrs.length - 1;
int m = 0;
while(low <= high) {
m = low + (high - low) / 2;
//只要target小于等于就往左移
if(arrs[m] >= target) {
high = m - 1;
} else {
low = m +1;
}
}
if(low < arrs.length && arrs[low] == target) {
return low;
}
return -1;
}
2、查找最后一个与target相等的元素
/** * 查找最后一个与target相等的元素 * * @param arrs * @param target * @return */
public static int findLastEqual(int[] arrs, int target) {
int low = 0;
int high = arrs.length - 1;
int m = 0;
while(low <= high) {
m = low + (high - low) / 2;
//只要target小于等于就往右移
if(arrs[m] <= target) {
low = m +1;
} else {
high = m - 1;
}
}
if(high >= 0 && arrs[high] == target) {
return high;
}
return -1;
}
3、查找最后一个小于target的元素
/** * 查找最后一个小于target的元素.也就是说返回小于target的最右边元素下标。 * * @param arrs * @param target * @return */
public static int findLastSmaller(int[] arrs, int target) {
int low = 0;
int high = arrs.length - 1;
int m = 0;
while(low <= high) {
m = low + (high - low) / 2;
//条件就是题目中的小于target
if(arrs[m] < target) {
low = m +1;
} else {
high = m - 1;
}
}
//返回最右边
return high;
}
4、查找第一个等于或者大于target的元素
/** * 查找第一个等于或者大于target的元素 * * @param arrs * @param target * @return */
public static int findFirstEqualLarger(int[] arrs, int target) {
int low = 0;
int high = arrs.length - 1;
int m = 0;
while(low <= high) {
m = low + (high - low) / 2;
//条件就是题目中的等于或者大于target
if(arrs[m] >= target) {
high = m - 1;
} else {
low = m +1;
}
}
//返回最左边
return low;
}