本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的。同时也希望文章能够让你有所收获,与君共勉!

今天主要学习二分法查找,二分主要分为两种类型,一种是整数二分查找,一种是浮点数二分查找。先看看整数二分,其模板如下:

整数二分

//查找左边界 SearchLeft 简写SL
int SL(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
//查找右边界 SearchRight 简写SR
int SR(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1; //需要+1 防止死循环
if (check(mid)) l = mid;
else r = mid - 1;
}
return r;
}

最有效的方式就是通过题目来理解二分。

数的范围

给定一个按照升序排列的长度为 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

个人解析



引用自[https://www.acwing.com/solution/content/107848/]

我们可以理解为我们只需要找到这个数组成的区间左端点和右端点即可知道这段区间的位置,而查找左端点和右端点就可以使用二分来快速的查找(当然暴力也可以做)。

1.我们先考虑查找左端点时所需要的条件, 比较a[mid]x,什么时候这个条件成立时能缩小右端点r = mid,反之,条件不成立时,缩小左端点l = mid+1我们可以想到,当a[mid]x大时,需要往左边寻找,当a[mid]x小时,需要往右边寻找,最终找到结果时一定有l==r(因为循环条件l<r)

2.再来考虑右端点的条件,参考查找左端点,我们需要尽可能地改变左端点l = mid,因此结论为,当a[mid]x要小时,要往右边寻找,当a[mid]x要大时,要往左边寻找。

3.需要注意的是,模板中找左端点时mid = l + r >> 1,而找右端点时mid = l+r+1 >> 1,我们怎么来分辨什么时候+1,什么时候不+1呢,并且很多题目都不会明确告诉你要求区间端点。这时我们可以看条件成立时Check(a[mid],x)的缩小区间这一步,如果为r=mid就不需要+1,如果为l=mid就需要+1。

综上,这道题算是完成了。

代码实现

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int q[100000];
int main(void){
int n,m;
cin >> n >> m;
for(int i=0; i < n ; ++i) cin >> q[i];
while(m--){
int l = 0,r = n-1,x;
cin >> x;
// 1.找到区间的左端,满足条件(x将区间分为两段,要找右端的最左边,满足x右端数的条件往左边缩小范围)
while( l<r ){
int mid = l + (r-l)/2;
if(q[mid] >= x){
r = mid;
}
else{
l = mid + 1;
}
}
if(q[l] != x){
cout << "-1" << " " << "-1" <<endl;
}
else{
cout << l << ' ';
l = 0 , r = n-1;
// 满足x左端数的条件往右边缩小,找最大值,注意往右边缩小范围时要+1防止向下取整
while(l<r){
int mid = (l+r+1)/2;
if(q[mid] <= x){
l = mid;
}
else{
r = mid-1;
}
}
cout << r << endl;
}
}
return 0;
}

力扣上跟这道题很像的二分:点击这里

浮点数二分

这就比较简单了,不需要考虑找边界,就是找一个浮点数呗,因此退出循环的条件也变成了r-l小于很小的数时才会退出。

模板为:

bool check(double x) {/* ... */} // 检查x是否满足某种性质

double bsearch_3(double l, double r)
{
const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}

这道浮点数二分的题就是模板:数的三次根

2022-11-03 Acwing每日一题的更多相关文章

  1. [ 10.03 ]CF每日一题系列—— 534B贪心

    Descripe: 贪心,贪在哪里呢…… 给你初始速度,结尾速度,行驶秒数,每秒速度可变化的范围,问你行驶秒数内最远可以行驶多少距离 Solution: 贪心,我是否加速,就是看剩下的时间能不能减到原 ...

  2. CISP/CISA 每日一题 11

    CISA 每日一题(答) 一个合理建造的数据仓库应当支持下列三种基本的查询格式: 1.向上溯源和向下溯源——向上溯源是对数据进行总计:向下溯源是将数据进行细化: 2.交叉溯源——通过通用属性访问数据仓 ...

  3. 老男孩IT教育-每日一题汇总

    老男孩IT教育-每日一题汇总 第几天 第几周 日期 快速访问链接 第123天 第二十五周 2017年8月25日 出现Swap file….already exists以下错误如何解决? 第122天 2 ...

  4. 【Java每日一题】20161122

    package Nov2016; import java.util.ArrayList; import java.util.Iterator; public class Ques1122 { publ ...

  5. PL/SQL Challenge 每日一题:2014-3-14 11gR2中带RELIES_ON子句的RESULT_CACHE函数

    PL/SQL Challenge 每日一题:2014-3-14 11gR2中带RELIES_ON子句的RESULT_CACHE函数 最先答对且答案未经编辑的puber将获得纪念章一枚(答案不可编辑但可 ...

  6. CISP/CISA 每日一题 五

    CISA 每日一题(答) 信息系统审计师要确认系统变更程序中的: 1.变更需求应有授权.优先排序及跟踪机制: 2.日常工作手册中,明确指出紧急变更程序: 3.变更控制程序应同时为用户及项目开发组认可: ...

  7. [每日一题]ES6中为什么要使用Symbol?

    关注「松宝写代码」,精选好文,每日面试题 加入我们一起学习,day day up 作者:saucxs | songEagle 来源:原创 一.前言 2020.12.23日刚立的flag,每日一题,题目 ...

  8. [每日一题]面试官问:谈谈你对ES6的proxy的理解?

    [每日一题]面试官问:谈谈你对ES6的proxy的理解? 关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...

  9. 【js】Leetcode每日一题-完成所有工作的最短时间

    [js]Leetcode每日一题-完成所有工作的最短时间 [题目描述] 给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间. 请你将这些工作分配给 k 位工人.所有工 ...

  10. 【JavaScript】Leetcode每日一题-青蛙过河

    [JavaScript]Leetcode每日一题-青蛙过河 [题目描述] 一只青蛙想要过河. 假定河流被等分为若干个单元格,并且在每一个单元格内都有可能放有一块石子(也有可能没有). 青蛙可以跳上石子 ...

随机推荐

  1. An iOS zero-click radio proximity exploit odyssey

    NOTE: This specific issue was fixed before the launch of Privacy-Preserving Contact Tracing in iOS 1 ...

  2. KingbaseES 匿名块如何传递参数

    匿名块的基本语法结构包括声明和执行两部分.匿名块每次提交都被重新编译和执行.因为匿名块没有名称并不在数据库中存储,所以匿名块不能直接从其他PL/SQL 块中调用. 定义语法: [ DECLARE ] ...

  3. 常用MySQL语句(持续更新)

    1. 客户端登录 在终端输入 mysql -u[用户名] -p[密码] 2. 数据库级别操作 // 创建数据库 create database [db name]; // 查看数据库列表 show d ...

  4. 【项目实战】Kaggle电影评论情感分析

    前言 这几天持续摆烂了几天,原因是我自己对于Kaggle电影评论情感分析的这个赛题敲出来的代码无论如何没办法运行,其中数据变换的维度我无法把握好,所以总是在函数中传错数据.今天痛定思痛,重新写了一遍代 ...

  5. 使用 Dockerfile 的一些最佳实践

  6. nginx日志参数及含义

    参数含义 $remote_addr,$http_x_forwarded_for #记录客户端IP地址 $remote_user #记录客户端用户名称 $request #记录请求的URL和HTTP协议 ...

  7. 查看pod对应的DNS域名

    单个pod # kubectl exec redis-pod-0 -n cluster-redis -- hostname -f redis-pod-0.redis-cluster-service.c ...

  8. C#-13 泛型

    一 泛型 泛型提供了一种更优雅的方式,可以让多个类型共享一组代码.泛型允许我们声明类型参数化的代码,可以用不同的类型进行实例化. 也就是说,我们可以用"类型占位符"来写代码,然后在 ...

  9. JavaScript之无题之让人烦躁的模块化

    我怎么记得我好像写过相关类型的文章,但是我找遍了我的博客没有-那就再写一遍吧,其实模块化的核心内容也算不上是复杂,只不过需要整理一下,规划一下罢了.嘻嘻. 开始写标题的时候我就在纠结一件事情,就是,先 ...

  10. 220722 T2 序列(ST表+分治)

    题目描述 小 B 喜欢玩游戏. 有一天,小 B 在玩一个序列上的游戏,他得到了正整数序列{ai}以及一个常数c . 游戏规则是,玩家可以对于每一个ai 分别加上一个非负整数x ,代价为 x2,完成所有 ...