一、查找已递增排序数组A中 大于等于(或者大于) 给定target的 第一个 元素的下标
//当eq_enable为true时 对应【大于等于】的情况
//当eq_enable为false时 对应【大于】的情况
int binarySearch_GE_or_G(vector<int>& A, int target, bool eq_enable) {
int left = 0, right = (int)A.size() - 1, ans = (int)A.size();
while (left <= right) {
//int mid = (left + right) / 2;
//上面的这种写法可能会造成int求和溢出,因此统一写成下面的这种形式
int mid = left + (right-left) / 2;
if (A[mid] > target || (eq_enable && A[mid] == target)) {
ans = mid; //标出可能成为答案的点
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
}
//若ans等于A.size()说明没有找到满足条件的值
二、查找已递增排序数组A中 小于等于(或者小于) 给定target的 最后一个 元素的下标
//当eq_enable为true时 对应【小于等于】的情况
//当eq_enable为false时 对应【小于】的情况
int binarySearch_LE_or_L(vector<int>& A, int target, bool eq_enable) {
int left = 0, right = (int)A.size() - 1, ans = (int)A.size();
while (left <= right) {
//int mid = (left + right) / 2;
//上面的这种写法可能会造成int求和溢出,因此统一写成下面的这种形式
int mid = left + (right-left) / 2;
if (A[mid] < target || (eq_enable && A[mid] == target)) {
ans = mid; //标出可能成为答案的点
left = mid + 1;
} else {
right = mid - 1;
}
}
return ans;
}
同样,若ans等于A.size()说明没有找到满足条件的值。此外,代码2和代码1十分相似,可以对比学习
总结:
第一次看上面的代码可能会觉得比较奇怪,多思考几种不同的情形做遍历就能够熟悉了,核心思想为:
利用位置mid和数组的有序性作排除法,确定下一个可疑区是[left,mid-1] 还是 [mid+1,right],经过不断地重复mid判断和可疑区长度减半,最终就能实现找点的功能了。
扩展
作为练习,感兴趣的读者可以试试实现一下以下两个需求:
三、查找已递减排序数组A中 小于等于(或者小于) 给定target的 第一个 元素的下标
四、查找已递减排序数组A中 大于等于(或者大于) 给定target的 最后一个 元素的下标