什么时候用二分查找?
数据具有二段性的时候
第一题:
题解代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0,right = nums.size()-1;
while(left<=right){
int mid = left+ (right-left)/2;//中间,left+区间长度
if(nums[mid]>target){
right = mid-1;
}
else if(nums[mid]<target){
left = mid+1;
}
else return mid;
}
return -1;
}
};
总结朴素二分查找的模板:
while(left<=right){//切记这里是<=
int mid = left+ (right-left)/2;//防止溢出的写法
if(..........){
right = mid-1;
}
else if(............){
left = mid+1;
}
else return ........;
}
第二题:
题解代码:
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
//特殊处理
if(nums.size() == 0) return {-1,-1};
int left = 0,right = nums.size()-1;
int begin = 0;
//二分⬅左端点
while(left<right){
//求中间
int mid = left+(right-left)/2;
if(target>nums[mid]) left = mid +1;
else right = mid;
}
//判断是否有结果
if(nums[left] != target) return {-1,-1};
else begin = left;
//二分右端点
right = nums.size()-1;
while(left<right){
int mid = left+(right-left+1)/2;
if(target>= nums[mid]) left = mid;
else right = mid-1;
}
return {begin,right};
}
};
总结二分模板:
1、查找区间左端点的模板
//查找区间左端点的模板
while(left<right){
//求中间
int mid = left+(right-left)/2;
if(、、、、、、) left = mid +1;
else right = mid;
}
2、查找区间有端点的模板:
while(left<right){
int mid = left+(right-left+1)/2;
if(、、、、、) left = mid;
else right = mid-1;
}
3、帮助记忆的几句话:
1、下面用减上面就用加1;
2、下面按情况讨论;
第三题:
题解代码:
class Solution {
public:
int mySqrt(int x) {
//处理特殊的额情况
if(x<1) return 0;
int left = 1,right = x;
//固定的模板
while(left<right){
long long mid = left+(right-left+1)/2;
if(mid*mid<=x) left = mid;
else right = mid-1;
}
return left;
}
};
第四题:
题解代码:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0,right = nums.size()-1;
while(left<right){
int mid = left+(right-left)/2;
if(nums[mid]>= target) right = mid;
else left = mid+1;
}
//处理一下特殊的情况
if(nums[left]< target) return nums.size();
return left;
}
};
第五题:

题解思路:
所以代码如下:
class Solution {
public:
int peakIndexInMountainArray(vector<int>& arr) {
//分析:峰顶的元素一定严格大于前一个数,但是不一定大于后面的元素;
int left = 1,right = arr.size()-2;
//查找的位置的元素一定大于前面一个,小于或者等于后面一个
while(left<right){
int mid = left+(right-left+1)/2;
if(arr[mid]>arr[mid-1]) left = mid;
else right = mid-1;
}
return left;
}
};