代码来自 胡凡著的《算法笔记》一书,记录学习过程中的新的心得~
解决“寻找有序序列第一个满足某条件的元素的位置”问题的固定模板
1.二分区间为左闭右闭的[left,right],初值必须能够覆盖解的所有可能取值
int solve(int A[], int left, int right, int x) {
int mid;
while(left < right) {
mid = (left + right) /2;
if(条件成立) { //条件成立,第一个满足条件的元素的位置<=mid
right = mid; //往左子区间 [ left , mid ] 查找
} else { //条件不成立,则第一个满足该条件的元素的位置>mid
left = mid + 1; //往右子区间 [ mid+1 , right ] 查找
}
}
return left; //返回夹出来的位置
}
2.二分区间为左开右闭的 ( left , right ],初值必须能够覆盖解的所有可能取值,并且left比最小取值小1
int solve(int A[], int left, int right, int x) {
int mid;
while(left + 1 < right) {
mid = (left + right) /2;
if(条件成立) { //条件成立,第一个满足条件的元素的位置<=mid
right = mid; //往左子区间 [ left , mid ] 查找
} else { //条件不成立,则第一个满足该条件的元素的位置>mid
left = mid; //往右子区间 [ mid , right ] 查找
}
}
return right; //返回夹出来的位置
}
3.查找序列中是否存在满足某条件的元素
#include <cstdio>
int binarySearch(int A[], int left, int right, int x) {
int mid;
while(left <= right) { //如果 left>right 就没办法形成闭区间了
mid = (left + right) / 2; //取中点
if(A[mid] == x) return mid; //找到 x, 返回下标
else if(A[mid] > x) { // 中间的数大于 x
right = mid - 1; // 往左子区间 [ left , mid-1 ] 查找
} else { // 中间的数小于 x
left = mid + 1; // 往右子区间 [ mid+1 , right] 查找
}
}
return -1; //查找失败,返回-1
}
4.upper_bound
寻找第一个满足条件“值大于x”的元素的位置
A[ ] 为递增序列,x 为欲查询的数,函数返回第一个大于 x 的元素的位置
二分上下界为左闭右闭的 [ left , right ] ,传入的初值为 [ 0 , n ]
int upper_bound(int A[], int left, int right, int x) {
int mid;
while(left < right) { //对 [left,right] 来说,left=right 意味着找到唯一位置
mid = ( left + right ) / 2;
if(A[mid] > x) {
right = mid;
} else {
left = mid + 1;
}
}
return left; //返回夹出来的位置,此时 left = right
}
5.lower_bound
寻找第一个满足条件“值大于等于x”的元素的位置
与upper_bound的差别在于 A[mid] >= x
int upper_bound(int A[], int left, int right, int x) {
int mid;
while(left < right) { //对 [left,right] 来说,left=right 意味着找到唯一位置
mid = ( left + right ) / 2;
if(A[mid] >= x) {
right = mid;
} else {
left = mid + 1;
}
}
return left; //返回夹出来的位置,此时 left = right
}