在有序数组中确定num存在还是不存在
public static boolean exist(int[] arr, int num) {
if (arr == null || arr.length == 0) {
return false;
}
int l = 0, r = arr.length - 1, m = 0;
while (l <= r) {
m = (l + r) / 2;
if (arr[m] == num) {
return true;
} else if (arr[m] > num) {
r = m - 1;
} else {
l = m + 1;
}
}
return false;
}
在有序数组中找>=num的最左位置
中>=num,记答案,往左二分;中<num,不记答案,往右二分
public static int findLeft(int[] arr, int num) {
int l = 0, r = arr.length - 1, m = 0;
int ans = -1;
while (l <= r) {
// m = (l + r) / 2;
// m = l + (r - l) / 2;
m = l + ((r - l) >> 1); // 可以防止溢出
if (arr[m] >= num) {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
在有序数组中找<=num的最右位置
中>num,不计答案,往左二分;中<=num,记答案,往右二分
public static int findRight(int[] arr, int num) {
int l = 0, r = arr.length - 1, m = 0;
int ans = -1;
while (l <= r) {
m = l + ((r - l) >> 1);
if (arr[m] <= num) {
ans = m;
l = m + 1;
} else {
r = m - 1;
}
}
return ans;
}
二分搜索不一定发生在有序数组上(比如寻找峰值问题)
leetcode 162.寻找峰值 medium
leetcode 852.山脉数组的峰顶索引 medium
public static int findPeakElement(int[] arr) {
int n = arr.length;
if (arr.length == 1) {
return 0;
}
if (arr[0] > arr[1]) {
return 0;
}
if (arr[n - 1] > arr[n - 2]) {
return n - 1;
}
int l = 1, r = n - 2, m = 0, ans = -1;
while (l <= r) {
m = (l + r) / 2;
if (arr[m - 1] > arr[m]) {
r = m - 1;
} else if (arr[m] < arr[m + 1]) {
l = m + 1;
} else {
ans = m;
break;
}
}
return ans;
}