一、二分查找
其本质就是找一个区间
二、整数二分
2.1. 查找左边界的模板
int findPrior(int left,int right,int target) {
while (left < right) {
int mid = (left + right) / 2;
if (a[mid] >= target) right = mid;
else left = mid + 1;
}
if (a[left] == target) return left;
else return false;
}
2.2. 查找右边界模板
int findTail(int left, int right, int target) {
while (left < right) {
int mid = (left + right + 1) / 2;
if (a[mid] <= target) left = mid;
else right = mid - 1;
}
if (a[left] == target) return left;
return false;
}
两个模板之间的区别在于,mid的边界取值问题。当找右边界时,mid=(left+right+1)/2,是为了防止其死循环,可以举例,当左指针在左边界,而右指针在其下一个位置,此时如果满足的是a[mid]<=target这一条件,左指针就会一直呆在左边界,此时陷入死循环。
如何记忆呢?答:看到left=mid,那么mid边界取值肯定是(left+right+1)/2,否则就是(left+right)/2。
2.2. 相关题目
#include<stdio.h>
int main() {
int n;
int q;
int k;
int a[100010];
scanf("%d %d", &n, &q);
for (int i = 0; i < n; i++)
scanf("%d", a + i);
while (q--) {
scanf("%d", &k);
int left = 0;
int right = n;
while (left < right) {
int mid = (left + right) / 2;
if (a[mid] >= k) right = mid;
else left = mid + 1;
}
if (a[left] != k)
printf("-1 -1\n");
else {
printf("%d ", left);
left = 0; right = n - 1;
while (left < right) {
int mid = (left + right + 1) / 2;
if (a[mid] <= k) left = mid;
else right = mid - 1;
}
printf("%d\n", left);
}
}
}
三、浮点数二分
3.1. 相关题目
#include<stdio.h>
#include<math.h>
int main(){
double n;
scanf("%lf",&n);
double left = -10000,right = 10000;
while (right - left >= 1e-8) {
double mid = (left + right) / 2;
if (mid * mid * mid <= n) left = mid;
else right = mid;
}
printf("%.6f",left);
return 0;
}