今天看完《算法笔记》里二分法这个章节,稍微总结一下。
二分法的思想主要就是折半查找,达到O(logn)的查找速度。
使用目的或者说使用情景主要有如下三个,下面将依次介绍。
- 查找有序序列中是否存在满足条件的元素
- 查找有序序列中满足条件的第一个元素
- 对一些函数进行求根(近似)计算
1. 查找有序序列中是否存在满足条件的元素
下面的函数是找到a[]数组中是否有等于x的元素,如果有返回索引下标,如果没有则返回-1。
要注意二分的使用条件是序列有序,下面代码中的判断条件可以根据使用需求进行修改。
对于一些下标快达到int上限的搜索区间时,可以把
mid = (left + right) / 2;
替换为
mid = left + (right - left) / 2;
int binary_search(int a[], int left, int right, int x) {
int mid;
while (left < right) {
mid = (left+right) / 2;
if (a[mid] == x) return mid;
if (a[mid] > x) { // 可以根据具体使用需求修改条件
right = mid - 1;
}
else {
left = mid + 1;
}
}
return -1;
}
2.查找有序序列中满足条件的第一个元素
下面的函数是找到a[]数组中等于x的第一个元素的索引下标。
同样的,代码中的判断条件可以根据使用需求进行修改。
int binary_search(int a[], int left, int right, int x) {
int mid;
while (left < right) {
mid = (left+right) / 2;
if (a[mid] >= x) { // 条件可以根据需求进行修改
right = mid;
}
else {
left = mid + 1;
}
}
return left;
}
3.对一些函数进行求根(近似)计算(求根号2近似值为例)
const int eps = 1e-5; // 求根精度为1e-5
double f(double x) {
return x*x-2;
}
int solve(double L, double R) { // L R为求根区间
int l = L, r = R, mid = (l + r) / 2;
while (r - l < eps) {
mid = (l + r) / 2;
if (f(mid) > 0) {
r = mid;
}
else {
l = mid;
}
}
return mid;
}