二分查找刷题2

 刷题的书目在 上一篇文章里提到过了,大家可以看下上一篇的文章,暂时刷题参考的书是这些,如果有更换,会及时说明。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。

书上的例子:

二分查找刷题2_第1张图片

           图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。

你可能感兴趣的:(算法,数据结构,c++)