二分的思想就是每次都排除一半的数据
二分查找的适用场合:
1.对于给定的已经有序的数列,需要在该数列中查找是否存在某个元素
2.在单调的有序的范围中,寻找符合问题 解 的一个解
1.递归版 *数列中找k
int left = 0 , right = vec.size() - 1;
int bsearch(int left,int right,int k){
if(left <= right){
int mid = (left + right) >> 1;
if (vec[mid] == k) return mid;
if (vec[mid] > k) return bsearch(left, mid - 1, k);
if (vec[mid] < k) return bsearch(mid + 1, right, k);
}
return -1 ;
}
2.非递归版 *数列中找k
int left = 0 , right = vec.size() - 1;
int bsearch(int left,int right,int k){
while(left <= right){
int mid = (left + right) >> 1;
if(vec[ mid ] == k) return mid;
if(vec[ mid ] > k) right = mid - 1;
if(vec[ mid ] < k) left = mid + 1;
}
return -1;
}
//如果只是在范围内求 k 把 vec [ mid ] 改成 mid 即可
eg:在数组 1 2 3 4 5 6 中 ,找 3 。
3.求上限 *满足 小于 k 的最大解(solve 单调增
int left = min , right = max ; // max -> 右边界 , min -> 左边界
int bsearch(int left,int right,int k){
int ans = -1;
while(left <= right){
int mid = (left + right) >> 1;
if(solve( mid ) >= k) right = mid - 1;
else { left = mid + 1; ans = mid; }
}
return ans;
}
4.求下限 *满足 大于 k 的最小解(solve 单调增
int left = min , right = max ; // max -> 右边界 , min -> 左边界
int bsearch(int left,int right,int k){
int ans = -1;
while(left <= right){
int mid = (left + right) >> 1;
if(solve( mid ) <= k) left = mid + 1;
else { right = mid - 1; ans = mid; }
}
return ans;
}
//3.4. solve 也必须是单调的,如果 solve 的单调和 mid 的单调相反,板子反着用
class Solution {
public:
double solve(vector<int>& dist,int mid){
double sum = 0;
vector<int>::iterator it;
for(it = dist.begin();it != dist.end();it ++){
if(it+1 != dist.end()) sum += ceil((double) *it / mid);
else sum += (double)*it / mid;
}
return sum;
}
int bsearch(vector<int>& dist,int left,int right,double hour){
int ans = -1;
while(left <= right){
int mid = (left + right) >> 1;
if(solve(dist,mid) <= hour){ right = mid - 1; ans = mid; }
else left = mid + 1;
}
return ans;
}
int minSpeedOnTime(vector<int>& dist, double hour) {
int left = 0 , right = 0x3f3f3f3f;
int mid = bsearch(dist , left , right , hour);
return mid;
}
};