while(left < right) {
long long mid = (left + right + 1) / 2;
long long now = fun(mid);
if(now >= m) {
left = mid;
} else {
right = mid - 1;
}
}
对于 left = mid, 左边界如果为 mid 了, 且下一次循环时 mid 等于 left 就会造成死循环, 所以我们需要控制mid 向上取.
至于为什么要 left = mid 是题目要求答案尽可能的高
如果数据之间的比较操作非常耗时,不管数据量大小,我都推荐使用二分查找。比如,数组中存储的都是很长的字符串,如此长的两个字符串之间比对大小,就会非常耗时。
我们需要尽可能地减少比较次数,而比较次数的减少会大大提高性能,这个时候二分查找就比顺序遍历更有优势。
查找第一个值等于给定值的元素
// 变种一:有序数组存在重复数据,查找第一个值等于给定值的元素
int binarySearch(int *a, int n, int value) {
if (n == 0) return -1;
if (n == 1) return 0;
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] < value) {
low = mid + 1;
} else if (a[mid] > value) {
high = mid - 1;
} else {
if (mid == 0 || a[mid - 1] != value) return mid;
high = mid - 1;
}
}
return -1;
}
查找最后一个值等于给定值的元素
// 变种二:有序数组存在重复数据,查找最后一个值等于给定值的元素
int binarySearch(int *a, int n, int value) {
if (n == 0) return -1;
if (n == 1) return 0;
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] < value) {
low = mid + 1;
} else if (a[mid] > value) {
high = mid - 1;
} else {
if (mid == n - 1 || a[mid + 1] != value) return mid;
low = mid + 1;
}
}
return -1;
}
查找第一个大于等于给定值的元素
// 变种三:有序数组存在重复数据,查找第一个大于等于给定值的元素
int binarySearch(int *a, int n, int value) {
if (n == 0) return -1;
if (n == 1) return 0;
int low = 0;
int high = n- 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] >= value) {
if (mid == 0 || a[mid - 1] < value) return mid;
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
查找最后一个小于等于给定值的元素
int binarySearch(int *a, int n, int value) {
if (n == 0) return -1;
if (n == 1) return 0;
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] <= value) {
if (mid == n - 1 || a[mid + 1] > value) return mid;
low = mid + 1;
} else {
high = mid - 1;
}
}
return -1;
}