基本模板
int binSearch(vector<int>& nums, int target) {int lo=0;int hi=(...)//key 1while(...){ //key 2int mi=lo+((hi-lo)>>1);if(nums[mi]<target){(...)//key3}else if(nums[mi]==target){(...)//key3}else if(nums[mi]>target){(...)//key3}}return (...);}
version 1
int binSearch(vector<int>& nums, int target) {int lo=0;int hi=nums.size()-1;//key 1: 因为是左闭右闭区间while(lo<=hi){ //key 2 :左闭右闭区间 [lo, hi],判断结束的条件!int mi=lo+((hi-lo)>>1);if(nums[mi]<target){lo=mi+1;//[mi+1,hi]}else if(nums[mi]==target){return mi;//命中返回}else if(nums[mi]>target){hi=mi-1;//[lo,mi-1]}}return -1;}
:::tips
- 左闭右闭区间
- 右边界可以取到,所以一开始是
nums.size()-1 - 判断命中即返回,有缺陷,找到的并不是右边第一个数或是左边第一个数
- 更新时的区间需要排除mid
:::
左闭右开区间版本
```cpp
int binSearch(vector
& nums, int target) { int lo=0; int hi=nums.size();//key 1: 因为是左闭右开
- 右边界可以取到,所以一开始是
while(lo<hi){ //key 2 :左闭右闭区间 [lo, hi],判断结束的条件!int mi=lo+((hi-lo)>>1);if(nums[mi]<target){lo=mi+1;//[mi+1,hi)}else if(nums[mi]>=target){hi=mi;//[lo,mi)}}return nums[lo]==target?lo:-1;}
<a name="zWo2X"></a># 寻找左侧边界的二分搜索```cppint binSearch(vector<int>& nums, int target) {int lo=0;int hi=nums.size();//key 1: 因为是左闭右开while(lo<hi){ //key 2 :左闭右闭区间 [lo, hi),判断结束的条件!int mi=lo+((hi-lo)>>1);if(nums[mi]==target){hi=mi;//key!}else if(nums[mi]<target){lo=mi+1;//[mi+1,hi)}else if(nums[mi]>target){hi=mi;//[lo,mi)}}if(lo>nums.size()) return -1;return nums[lo]==target?lo:-1;}
找到 target 时不要立即返回,而是缩小「搜索区间」的上界 right,在区间[left, mid) 中继续搜索,即不断向左收缩,达到锁定左侧边界的目的。
寻找右边界
int binSearch(vector<int>& nums, int target) {int lo=0;int hi=nums.size();//key 1: 因为是左闭右开while(lo<hi){ //key 2 :左闭右闭区间 [lo, hi),判断结束的条件!int mi=lo+((hi-lo)>>1);if(nums[mi]==target){lo=mi+1;//key!}else if(nums[mi]<target){lo=mi+1;//[mi+1,hi)}else if(nums[mi]>target){hi=mi;//[lo,mi)}}if(lo==0) return -1;return nums[lo-1]==target?lo-1:-1;}
左闭右闭区间
int findLe(vector<int>& nums, int target){int lo=0;int hi=nums.size()-1;while(lo<=hi){int mi=lo+((hi-lo)>>1);if(nums[mi]==target){hi=mi-1;}else if(nums[mi]<target){lo=mi+1;}else if(nums[mi]>target){hi=mi-1;}}if(lo>=nums.size()||nums[lo]!=target) return -1;return lo;}int findRi(vector<int>& nums, int target){int lo=0;int hi=nums.size()-1;while(lo<=hi){int mi=lo+((hi-lo)>>1);if(nums[mi]==target){lo=mi+1;}else if(nums[mi]>target){hi=mi-1;}else if(nums[mi]<target){lo=mi+1;}}if(hi<0||nums[hi]!=target) return -1;return hi;//lo-1;}
左闭右开区间
int findRi(vector<int>& nums, int target) {int lo=0;int hi=nums.size();while(lo<hi){int mi=lo+((hi-lo)>>1);if(nums[mi]==target){lo=mi+1;}else if(nums[mi]<target){lo=mi+1;}else if(nums[mi]>target){hi=mi;}}if(hi==0) return -1;return nums[lo-1]==target?lo-1:-1;}int findLe(vector<int>& nums, int target) {int lo=0;int hi=nums.size();while(lo<hi){int mi=lo+((hi-lo)>>1);if(nums[mi]==target){hi=mi;}else if(nums[mi]>target){hi=mi;}else if(nums[mi]<target){lo=mi+1;}}if(lo==nums.size()) return -1;return nums[lo]==target?lo:-1;}
