二分查找及其拓展
1、最基础的二分查找
给定一个有序数组arr[],判断这个有序数组里面是否包含num数字
public static boolean find(int[] arr, int num) {
if (arr == null || arr.length == 0) {
return false;
}
int L = 0;
int R = arr.length - 1;
int mid = L;
while (L <= R) {
mid = (R + L) / 2;
if (arr[mid] > num) {
R = mid - 1;
} else if (arr[mid] < num) {
L = mid + 1;
} else {
return true;
}
}
return false;
}
2、给定一个有序数组arr,查找大于等于num的最左侧的位置下标
/**
* arr有序 >=num 最左
*
* @param arr 有序数组
* @param num 查找的数
* @return 最左的>=num位置
*/
public static int mostLeftNoMorNumIndex(int[] arr, int num) {
if (arr == null || arr.length == 0) {
return -1;
}
int L = 0;
int R = arr.length - 1;
int ans = -1;
while (L <= R) {
int mid = (L + R) / 2;
if (arr[mid] >= num) {
ans = mid;
R = mid - 1;
} else {
L = mid + 1;
}
}
return ans;
}
3、给定一个有序数组arr,找到小于等于num最右的位置
public static int lessRightNoMorNumIndex(int[] arr, int num) {
if (arr == null || arr.length == 0) {
return -1;
}
int L = 0;
int R = arr.length - 1;
int ans = -1;
while (L <= R) {
int mid = (L + R) / 2;
if (arr[mid] <= num) {
ans = mid;
L = mid + 1;
} else {
R = mid - 1;
}
}
return ans;
}
4、局部最小值问题
arr数组是无序的,且arr任意两个相邻的数不相等,假设长度为0,局部最小的定义
arr[0] < arr[1] , 则0位置为局部最小
arr[N-2] > arr[N-1] , 则N-1位置为局部最小
arr[i-1] < arr[i] < arr[i+1],则i位置为局部最小
请你返回一个局部最小?
/**
* arr 整体无序,相邻的数不相等
*
* @param arr
* @return
*/
public static int oneMinIndex(int[] arr) {
if (arr == null || arr.length == 0) {
return -1;
}
int N = arr.length;
if (N == 1) {
return 0;
}
if (arr[0] < arr[1]) {
return 0;
}
if (arr[N - 1] < arr[N - 2]) {
return N - 1;
}
// arr.length> 2
int L = 0;
int R = N - 1;
while (L < R - 1) {
int mid = (R + L) / 2;
if ((arr[mid] < arr[mid + 1]) && (arr[mid - 1] > arr[mid])) {
// 左 < 我 < 右
return mid;
} else { // 不同时小
if (arr[mid] > arr[mid - 1]) {
// 左 < 我
R = mid - 1;
continue;
} else {
// 右 < 我
L = mid + 1;
continue;
}
}
}
return arr[L] < arr[R] ? L : R;
}