- Fdsama 的博客
二分查找
- 2024-1-21 20:46:03 @
Copyright by
引入
现在给出一个有序数组
和一个数x
求x在本数组的哪个位置第一次出现
法一:首先想到枚举,找到就输出
但是sei还这么做啊~
法二:借用二分答案的思路,二分第一次可能出现的区间即可
那么来一份可爱的代码吧~
#include<bits/stdc++.h>
using namespace std;
#define AwA 100010
int n;
int a[AwA];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int qwq;
cin >> qwq;
int l = 1, r = n;
while (l < r) {
int mid = (l + r) >> 1;
if (a[mid] < qwq) {
l = mid + 1;
} else {
r = mid;
}
}
cout << l << " " << a[l] << endl;
return 0;
}
通过输入我们可以发现
这份代码会返回的是第一个大于等于x的位置
同样,在原代码的基础上稍作修改可以返回第一个大于x的位置
#include<bits/stdc++.h>
using namespace std;
#define AwA 100010
int n;
int a[AwA];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int x;
cin >> x;
int l = 1, r = n;
while (l < r) {
int mid = (l + r) >> 1;
if (a[mid] <= x) {
l = mid + 1;
} else {
r = mid;
}
}
cout << l << " " << a[l] << endl;
return 0;
}
你说得对,但是……
我们还有法三:
有能力的同学要掌握的啊(bushi)
有个神奇的叫stl的东东,帮我们提前写好了上面两种算法:
直接拿来用就完事力(喜)
#include<bits/stdc++.h>
using namespace std;
#define AwA 100010
int n;
int a[AwA];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
int x;
cin >> x;
//lower_bound函数 返回第一个>=x的位置 如果没找到就会返回n+1
int x1 = lower_bound(a + 1, a + n + 1, x) - a;
cout << x1 << " " << a[x1] << endl;
//upper_bound函数 返回第一个>x的位置 如果没找到就会返回n+1
int x2 = upper_bound(a + 1, a + n + 1, x) - a;
cout << x2 << " " << a[x2] << endl;
//最后一个<x的位置
int x3 = x1 - 1;
cout << x3 << " " << a[x3] << endl;
//最后一个<=x的位置
int x4 = x2 - 1;
cout << x4 << " " << a[x4] << endl;
return 0;
}
~看起来像不像昨天某个哥哥讲的sort函数~
模板题
那么我们就可以来做题啦!
例2
#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[100010];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
cin >> m;
//注意数组一定是有序的才能二分
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
int l = 1, r = n + 1;
int t = m - a[i];
while (l < r) {
int mid = (l + r) >> 1;
if (a[mid] >= t) {
r = mid;
} else {
l = mid + 1;
}
}
if (l != n + 1 && a[l] == t && l != i) {
cout << a[i] << " " << a[l] << endl;
return 0;
}
}
cout << "No" << endl;
return 0;
}
或者
#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[100010];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
cin >> m;
//注意数组一定是有序的才能二分
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
int t = m - a[i];
int l = lower_bound(a + 1, a + n + 1, t) - a;
if (l != n + 1 && a[l] == t && l != i) {
cout << a[i] << " " << a[l] << endl;
return 0;
}
}
cout << "No" << endl;
return 0;
}
例3
#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[100010];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
cin >> m;
while (m--) {
int t;
cin >> t;
int l = lower_bound(a + 1, a + n + 1, t) - a;
if (l == n + 1) {
cout << a[n] << endl;
} else if (l == 1) {
cout << a[1] << endl;
} else {
if (a[l] - t < t - a[l - 1]) {
cout << a[l] << endl;
} else {
cout << a[l - 1] << endl;
}
}
}
return 0;
}
那么
完结撒花~awa
课后习题!!!
因为一本通没有剩下的二分查找的题了
所以这里从洛谷搞了几道