蓝桥杯系列之基础算法

2.1 整数二分

AcWing 789 数的范围

题目描述(以题带点 --)

给定一个按照升序排列的长度为 n 的整数数组,以及 q 个查询。

对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 0 开始计数)。

如果数组中不存在该元素,则返回 -1 -1。

输入格式

第一行包含整数 n 和 q,表示数组长度和询问个数。

第二行包含 n 个整数(均在 1∼10000 范围内),表示完整数组。

接下来 q 行,每行包含一个整数 k,表示一个询问元素。

输出格式

共 q 行,每行包含两个整数,表示所求元素的起始位置和终止位置。

如果数组中不存在该元素,则返回 -1 -1。

数据范围

1≤n≤100000
1≤q≤10000
1≤k≤10000

输入样例

    6 3
    1 2 2 3 3 4
    3
    4
    5

输入样例

     3  4
     5  5
    -1 -1

#include<bits/stdc++.h> //万能头-yyds
using namespace std;
const int N = 1e5 + 10; //n的范围(题干给的)
int n, q;
int a[N];
int l_find(int& ta)  //找起始位置的函数 (建议先看main函数)
{
	int l = 0, r = n - 1, m;  //定义一堆变量(眼花缭乱)
                              // l(不是数字1,是字母l“爱咯“) 是二分查找的左边界,r是右边界 ,你猜m是什么
	

while (l <= r)  
	{
		m = l + r >> 1;   // m = (l+r)/2

		if (a[m] >= ta) r = m - 1;  //如果数列中间那个值大于等于要找的目标值,把右边界提过来   二分查找的精髓

		else
			l = m + 1;   //否则就把左边界踢过去

	}

	if (l >= n || a[l] != ta)
		return -1;       //如果到最后还没有找到该元素 输出-1

	return l;   //把l 弹出

}


int r_find(int& ta)  //找终止位置的函数 (建议先看main函数)
{
	int l = 0, r = n - 1, m; 
	while(l<=r)
	{
		m = l + r >> 1;
		if (a[m] <= ta)   l = m + 1;
		else  r = m - 1;
	}

	if (r < 0 || a[r] != ta)
		return -1;

	return  r;

    //一句“同理可得”不过分吧
}



int main()
{
	ios::sync_with_stdio(false);  //加速cin cout 不必纠结,套用就好
	cin.tie(0);
	cout.tie(0);
	int i;
	cin >> n >> q;
	for (i = 0; i < n; ++i)
	{
		cin >> a[i];

	}
	while (q--)
	{
		cin >> i;
		cout << l_find(i) << " " << r_find(i) << endl;
	}
	
	

}

总结

二分法查找,概括来说,就是对于一段有序的数列,每次找到中间位置的值,通过与目标值比较过后确定目标值的区间,然后通过循环语句不断缩小区间,最后把目标值“夹”出来

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Changewyq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值