刷题的书目在 上一篇文章里提到过了,大家可以看下上一篇的文章,暂时刷题参考的书是这些,如果有更换,会及时说明。2024年希望自己以后多刷题,争取多多分享。不知道的小伙伴可以回看二分查找刷题-CSDN博客有说明书目喔。
本博客分享的刷题思路仅供参考,俗话说“一千个人眼中有一千个哈姆雷特”,或许大家有更好的想法,大家就当看看就好了。
题目来源:A-B 数对 - 洛谷
一开始做这道题的时候,没有认真审题(自罚三杯),我以为只是简单的相减用二分查找检索到就好了。其实不然,第一,题目没有明确说明它是一个顺序列表,第二元素是否相同,找到的元素若有多个时应该要cout++,第三真的要认真审题,我以为的是target= n-c,找target就好了。实际是元素之间相减要等于c。(哭晕~~)
书上的例子和代码说的很清楚,我就简单说下lower_bound和upper_bound的用法。
注:使用这两个函数时,一定是有序的序列。
lower_bound(begin,end,value):函数返回一个迭代器,指向在范围 [begin, end)
中第一个不小于 value
的元素。如果所有元素都小于 value
,则返回 end。
begin:指向要检查范围的第一个元素的迭代器
end:指向要检查范围的最后一个元素之后的迭代器
value:要查找的值。
upper_bound(begin,end,value):函数返回一个迭代器,指向在范围 [begin, end)
中第一个大于 value
的元素。如果所有元素都不大于 value
,则返回 end。
书上的例子:
图1 节选自《深入浅出程序设计竞赛--基础篇》例子
书上的思路是:用a=lower_bound(begin,end,value)函数找到第一个满足条件target=a[i]+c,用b=upper_bound(begin,end,value)函数找到最后一个满足条件的target。用cout 保存a-b的个数。
代码如下所示:
#include
#include
#define MAX 200010
using namespace std;
typedef long long LL;
LL a[MAX];
int n, c;
int main()
{
cin >>n >> c;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
sort(a, a + n); //排序
LL tot = 0;
for (int i = 0; i < n; i++)
{
tot += upper_bound(a, a + n, a[i] + c) - lower_bound(a, a + n,a[i] + c); //
}
cout << tot << endl;
return 0;
}
这个的时间复杂度是nlogn。书上还介绍了一个降低时间复杂度的方法。(时间复杂度是O(n))
#include
#include
#define MAX 200010
using namespace std;
typedef long long LL;
LL a[MAX];
int n, c;
int main()
{
cin >> n >> c;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
sort(a, a + n);
LL tot = 0;
for (int i = 0,L=0,R = 0; i < n; i++)
{
while (L < n && a[L] < a[i] + c)
{
L++;//相当于lower_bound
}
while (R < n && a[R] <= a[i] + c)
{
R++;//相当于upper_bound
}
tot += R - L;
}
cout << tot << endl;
return 0;
}
除了用二分查找,还可以用其他办法,仅供参考。
(1)双指针
#include
#include
#include
using namespace std;
int main() {
int N, C;
cin >> N >> C;
vector nums(N);
for (int i = 0; i < N; ++i) {
cin >> nums[i];
}
// 数组排序
sort(nums.begin(), nums.end());
int count = 0;
for (int i = 0; i < N; ++i) {
// 为每个 nums[i] 查找满足 nums[j] - nums[i] == C 的元素数量
int j = i + 1; // 初始化第二个指针
while (j < N && nums[j] - nums[i] <= C) {
if (nums[j] - nums[i] == C) {
count++;
}
j++;
}
}
cout << count << endl;
return 0;
}
(2) 枚举--时间复杂度高。(本题有限制,没限制可以用,多一条方法多点思路)
#include
#include
#include // 添加这个头文件以使用sort函数
using namespace std;
int main() {
int N, C;
cin >> N >> C;
vector nums(N);
for (int i = 0; i < N; i++) {
cin >> nums[i];
}
// 对数组进行排序
sort(nums.begin(), nums.end());
int count = 0;
for (int i = 0; i < N; i++) {
for (int j = i + 1; j < N; ++j) {
if (nums[j] - nums[i] == C) {
count++;
}
}
}
cout << count << endl; // 输出满足条件的数对数量
return 0;
}
ps:刷题的源代码在《深入浅出程序设计竞赛--基础篇》P177。