左侧二分模板:
左侧二分模板返回的是小于taget的序号
所以当l最后会有几种情况
- l < array.size() && v[l]== target 如1 2 2找 2
l = 1
意思是小于2的数有1个,因为数组从0 开始,所以正好就找到了2,但实际意义并非是2. 这种情况下,直接找到了target返回target就完事了 - l=0, 此时有两种情况,一是: array[0]恰好是target,此时和 1 情况重复,因此不必要再写,第二种情况:数组中没有比target小的元素
- l < array.size() && v[l]!= target找到的是小于target的数值, 如 1 3 找2,也就是常规的寻找比target小的第一个数
因此,增强模板为:
int l = 0, r = array.size();
while(l < r){
int mid = l + (r-l)/2;
if(array[mid] > target) r = mid;
else l = mid + 1;
if(l < array.size() && v[l]== target) return v[l]; //如 1 2 2找2 l = 1
else if(l == 0) return -xxxx; //如 1 3找 0 返回自定义标识
else return v[l-1]; // 如 1 3 找2
//若找不到不想反回比它小的数据
//if(l < array.size() && v[l]== target) return v[l]; //如 1 2 2找2 l = 1
//else return -1;
}
或者直接用c++的 upper_bound函数
但upper_bound函数也需要作区分
// lower_bound/upper_bound example
#include <iostream> // std::cout
#include <algorithm> // std::lower_bound, std::upper_bound, std::sort
#include <vector> // std::vector
int main () {
int myints[] = {10,20,30,30,20,10,10,20};
std::vector<int> v(myints,myints+8); // 10 20 30 30 20 10 10 20
std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
std::vector<int>::iterator low,low1;
low=std::lower_bound (v.begin(), v.end(), -1); // ^ ^
low1=std::lower_bound (v.begin(), v.end(), 100); //
std::cout << "lower_bound at position " << (low- v.begin()) << '\n';
std::cout << "lower_bound at position " << (low1- v.begin()) << '\n';
return 0;
}
结果是:
lower_bound at position 0
lower_bound at position 8
所以可以看出,该函数若找的值小于所有值,则返回0索引,若找的值大于所有值,则返回size()。其实和左侧二分代码是一样的。
右侧模板
int rightSearch(vector<int>& nums, int target){
int l = 0, r = nums.size();
while(l < r){
int mid = l + (r - l) / 2;
if(nums[mid] <= target) l = mid + 1;
else r = mid;
}
if(l-1 >=0 && nums[l-1] == target) return l-1;
else return -1;
}