详谈 二分搜索
1.二分搜索是什么?
答:一般在 单调 数组,通过不断缩小解的可能存在的范围,从而求得问题最优解的方法。
2.二分搜索干什么用的?
答:降低时间复杂度,普通枚举O(n),二分搜索O(log n)
3.二分搜索怎么写?
二分搜索,分为以下几个最重要的组成部分:
- L(左指针)
- R (右指针)
- mid (中间指针)
- while循环的判断条件(可以由1. 2.推出来)
- 所搜数组是有序的
while循环的判断条件:这样记“是闭就沾一”,我的意思是 左闭 left = mid+1, 右闭 right = mid-1 。“两闭加等于” 如果是两个闭区间 while(left <= right)
反之没有“=”
4.例题
例1.
给定长度为n的单调不下降数列a0…an-1和一个数k,求满足ai >= k条件的i。不存在的情况下输出n。
限制条件
- 1 <= n <= 1e6
- 0 <= a0 <= a1 <= … <= an-1 < 1e9
- 0 <= k <ae9
输入
n = 5
a = {2, 3, 3, 5, 6}
k = 3
输出
1
代码直接演示:
#include <bits/stdc++.h>
using namespace std;
const int maxl = 1e6;
int n, a[maxl], k, ans = 0;
int binary_search(int k){
int l = -1, r = n - 1; //左开右闭
while (l < r){
int mid = l + (r - l) / 2;
if(a[mid] == k){
return mid;
}
else if(a[mid] < k)
l = mid;
else
r = mid - 1; //是闭就沾一
}
return n;
/*
int l = 0, r = n - 1; //左闭右闭
while (l <= r){ //中间加等于
int mid = l + (r - l) / 2;
if(a[mid] == k){
return mid;
}
else if(a[mid] < k)
l = mid + 1; //是闭就沾一
else
r = mid - 1; //是闭就沾一
}
return n;
*/
/*
int l = 0, r = n; //左闭右开
while (l < r){
int mid = l + (r - l) / 2;
if(a[mid] == k){
return mid;
}
else if(a[mid] < k)
l = mid + 1; //是闭就沾一
else
r = mid;
}
return n;
*/
/*
int l = 0, r = n; //左开右开
while (l < r){
int mid = l + (r - l) / 2;
if(a[mid] == k){
return mid;
}
else if(a[mid] < k)
l = mid;
else
r = mid;
}
return n;
*/
}
int main(){
cin >> n;
for (int i = 0; i < n; i++){
cin >> a[i];
}
cin >> k;
sort(a, a + n);
ans = binary_search(k);
cout << ans;
}
值得关注的地方
如果查找的值中,不同下标有相同的的值,会满足这个要求,输出的下标值,靠“开”的那一边。
如例题:
输出的是1不是2,就是因为用的是“左开右闭”