二分查找(模板和应用)
二分查找的定义和用途,笔者觉得无需再多说什么,这里直接给出二分查找的两个模板,和一个简单例题,以供大家查阅和参考。
首先,二分查找是针对有序的单调不增或单调不减数组的,这应该没有问题,那么,在使用二分法的时候,记得先用 s o r t sort sort 函数对数组进行排序!
1.返回数组中待查找元素首次出现的位置
#include <iostream>
#include <algorithm>
using namespace std;
int a[15] = {0, 1, 4, 3, 3, 2, 4, 5, 7, 8, 4}; // 数组从1 开始计数,对“1, 4, 3, 3, 2, 4, 5, 7, 8, 4”这个区间使用二分查找制定元素首次出现的序号
int n = 10; // 数组的大小
// 二分
int find(int x)
{
int L = 1, r = n + 1; // 针对一个 [1,n+1) 的左开右闭区间
while (L < r)
{
int mid = L + (r - L) / 2; // 这样做是为了防止爆 int
if (a[mid] >= x)
r = mid; // 抛弃右边的所有数字,但不抛弃 a[mid]
else
L = mid + 1; // 抛弃左边所有数字 和 a[mid]
}
if (a[L] == x)
return L; // 此时返回的就是 x 在数组中第一个出现的位置
else
return -1;
}
int main()
{
sort(a+1,a+1+n);
int first = find(3); // 找3第一次出现的位置
cout << first;
return 0;
}
如果看不懂边界条件,先记住就行了!因为我也看不太懂
运行结果:
输出:3
2.返回数组中待查找元素最后一次出现的位置
#include <iostream>
#include <algorithm>
using namespace std;
int a[15] = {0, 1, 4, 3, 3, 2, 4, 5, 7, 8, 4}; // 数组从1 开始计数,对“1, 4, 3, 3, 2, 4, 5, 7, 8, 4”这个区间使用二分查找制定元素首次出现的序号
int n = 10; // 数组的大小
int find(int x)
{
int l = 1, r = n + 1;
while (l < r)
{
int mid = l + (r - l) / 2;
if (a[mid] <= x)
l = mid + 1;
else
r = mid;
} //while 运行结束后,l对应的是“最后一次出现的位置+1”,因此后续要减一
if (a[l - 1] == x)
return l - 1;
else
return -1;
}
int main()
{
sort(a + 1, a + 1 + n);
int ans = find(3);
cout << ans;
return 0;
}
运行结果:4
例题
洛谷P1102
题目分析:
转化为列举 A = B+ C,同时枚举B即可
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long
const int MA = 2e5 + 10;
ll a[MA], tol;
int n, c;
int main()
{
scanf("%d%d", &n, &c);
for (int i = 0; i < n; i++)
scanf("%lld", &a[i]);
sort(a, a + n);
ll tol = 0;
for (int i = 0; i < n; i++) // 枚举 B
{
int x = a[i] + c; // x 的值 对应的 就是 A 的值,枚举的a[i] 就是 B
// 二分找此时的 x (A) 第一次出现的位置
int l = i, r = n;
while (l < r)
{
int mid = l + (r - l) / 2;
if (a[mid] >= x)
r = mid;
else
l = mid + 1;
}
if (a[l] == x) // 找到了
{
// 接下来二分找 x(A) 最后一次出现的位置
int l2 = l, r2 = n;
while (l2 < r2)
{
int mid2 = l2 + (r2 - l2) / 2;
if (a[mid2] <= x)
l2 = mid2 + 1;
else
r2 = mid2;
}
if (a[l2 - 1] == x)
{
tol += l2 - l; // 由于此时的 l2 是“最后一次出现的位置” + 1,故直接相减即可
}
}
}
cout << tol;
return 0;
}
如果有错误,欢迎各位神犇指出。orz orz % %