二分算法(整数二分、浮点数二分)

文章目录

  • 二分
    • 一、整数二分
      • (一)整数二分思路
      • (二)整数二分算法模板
        • 1.左查找(寻找左侧边界)
        • 2.右查找(寻找右侧边界)
        • 3.总模板
      • (三)题目:数的范围
    • 二、浮点数二分
      • (一)浮点数二分思路
      • (二)浮点数二分算法模板
      • (三)题目:数的三次方根

二分

一、整数二分

(一)整数二分思路

在这里插入图片描述

(二)整数二分算法模板

在这里插入图片描述

1.左查找(寻找左侧边界)
  • 查找的情况分为三种:
    • 当a[mid]>2时,r=mid-1,l不变
    • 当a[mid]<2时,l=mid+1,r不变
    • 当a[mid]==2时,如果我们一找到就返回,那么,返回的结果将会是下标4,此时并不是目标值

​ 因此,我们需要向左缩小区间

  • 向左缩小区间:就是令r=mid,l不变;此时区间变为[0,4],既保证了下标为4的2保留在区间里,又保证可以继续查找[0,4]中是否还有数字2,如果[0,3]中没有数字2了,则下标4就会是该区间唯一一个满足条件的值,也就会是最终结果。而如果[0,3]中还有其他的2,就如本例,那么下标为4的数字就会被下一次缩小区间所抛弃。

  • 这里模拟一下样例:
    在这里插入图片描述
    最后l == r退出循环。此时如果r就是最终结果,那么l同时也是最终结果。另一种退出循环的方式就是l>r,l跑到r的右边,那么不管怎么说,l都不可能是最终目标。因此最后只用判断r是否是最终目标就好了

  • 判断r是否是x:如果退出循环后a[r]==x,说明找到了x,并且这个x是左边界的x;如果a[r]!=x,说明连x都找不到,返回-1;

  • 结果如下:

void query_l(int a)
{int l=0,r=n-1;while(l<r){int mid=(l+r)/2;if(arr[mid]==a)		r=mid;else if(arr[mid]>a)	r=mid-1;else				l=mid+1;}if(arr[l]==a)	cout<<r<<" ";else cout<<-1<<" ";
}

我们可以将等于和大于的情况合二为一,因为不管怎样最终都是要判断r是否为目标值的。所以,升级后的代码如下。

void query_l(int a)
{int l=0,r=n-1;while(l<r){int mid=(l+r)/2;if(arr[mid]>=a)	r=mid;else l=mid+1;}if(arr[l]==a)	cout<<r<<" ";else	cout<<-1<<" ";
}
2.右查找(寻找右侧边界)
  • 右查找就是要找到最后出现的值,不断向右缩小区间。分析过程与左查找类似。
  • 需要注意的一点,右查找和左查找确定mid值的方式不同。左查找采用(l+r)/2向下取整的方式,右查找采用(l+r+1)/2向上取整的方式。
  • 原因分析:
  • 对于左查找:假设l=2,r=3,向下取整得到的mid=(2+3+1)/2=3,若取r=mid,那么l和r任保持原值不变,陷入死循环。
  • 对于右查找:假设l=2,r=3,向下取整得到mid=(2+3)/2=2。若取l=mid,那么l和r任保持原值不变,陷入死循环。
    在这里插入图片描述
void query_r(int a)
{int l=0,r=n-1;while(l<r){int mid=(l+r+1)/2;if(arr[mid]<=a)	l=mid;else			r=mid-1;}if(arr[r]==a)	cout<<r;else	cout<<-1;
}
3.总模板
bool check(int x) {/* ... */} // 检查x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{while (l < r){int mid = l + r >> 1;if (check(mid)) r = mid;    // check()判断mid是否满足性质else l = mid + 1;}return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{while (l < r){int mid = l + r + 1 >> 1;if (check(mid)) l = mid;else r = mid - 1;}return l;
}

(三)题目:数的范围

给定一个按照升序排列的长度为 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<iostream>
using namespace std;
const int N = 100010;int n,m;
int q[N];int main()
{scanf("%d %d",&n,&m);for(int i=0;i<n;i++)scanf("%d",&q[i]);while(m--){int x;scanf("%d",&x);int l=0,r=n-1;while(l<r){int mid=(l+r)/2;if(q[mid]>=x)r=mid;else l=mid+1;}if(q[l]!=x)cout<<"-1 -1"<<endl;else{cout<<l<<" ";int l=0,r=n-1;while(l<r){int mid=(l+r+1)/2;if(q[mid]<=x)l=mid;elser=mid-1;}cout<<l<<endl;}}return 0;
}

二、浮点数二分

(一)浮点数二分思路

思路和整数二分一样,区别是浮点型二分不需要注意边界问题(也就是不需要+1)

(二)浮点数二分算法模板

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;
}

(三)题目:数的三次方根

题目描述

给定一个浮点数n,求它的三次方根。

输入格式
共一行,包含一个浮点数n。

输出格式
共一行,包含一个浮点数,表示问题的解。

注意,结果保留6位小数。

数据范围
−10000≤n≤10000

输入样例

1000.00

输出样例:

10.000000
#include<iostream>
using namespace std;
int main()
{double x;cin>>x;double l=-100,r=100;//根据题目范围 开三次方根 估计答案大概范围while(r-l>1e-8){double mid=(l+r)/2;if(mid*mid*mid>=x)r=mid;elsel=mid;}printf("%.6lf\n",l);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/234988.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一键删除方舟编译器缓存文件js、js.map插件ArkCompilerSupport

新手学习鸿蒙开发&#xff0c;发现DevEco Studio编译过种会生成js、js.map&#xff0c;在论坛上看了其它开发者也提了问题但无没解决&#xff0c;写了一个插件大家试下&#xff1a; https://plugins.jetbrains.com/plugin/23192-arkcompilersupport 源码&#xff1a;https://g…

咨询+低代码,强强联合为制造业客户赋能

内容来自演讲&#xff1a;沈毅 | 遨睿智库 | 董事长 & 王劭禹 | 橙木智能 | 联合创始人 摘要 文章主要讲述了智库董事长沈毅创办广告公司的经历&#xff0c;以及他在管理公司过程中遇到的问题和挑战&#xff0c;最后通过与明道云以及橙木智能联合创始人王邵禹老师的合作&…

Ubuntu systemd-analyze命令(系统启动性能分析工具:分析系统启动时间,找出可能导致启动缓慢的原因)

文章目录 Ubuntu systemd-analyze命令剖析目录简介systemd与systemd-analyze工作原理 安装和使用命令参数详解用例与示例显示启动时间&#xff08;systemd-analyze time&#xff09;列出启动过程中各个服务的启动时间&#xff08;systemd-analyze blame&#xff09;显示系统启动…

使用JDBC操作数据库时,插入数据中文乱码

如图&#xff1a; 解决办法&#xff1a; 修改连接数据库的路径&#xff0c;即url 如下&#xff1a; 设置编码格式为utf-8 urljdbc:mysql://localhost:3306/qfedu?useUnicodetrue&characterEncodingUTF-8再次运行&#xff0c;插入数据即可

XTU OJ 1339 Interprime 学习笔记

链接 传送门 代码 #include<bits/stdc.h> using namespace std;const int N1e610; //78498 我计算了一下&#xff0c;6个0的范围内有这么多个素数&#xff0c;所以开这么大的数组存素数 //计算的代码是一个循环 int prime[80000]; int a[N],s[N];//s数组是前缀和数组b…

vscode Markdown 预览样式美化多方案推荐

优雅的使用 vscode写 Markdown&#xff0c;预览样式美化 1 介绍 我已经习惯使用 vscode 写 markdown。不是很喜欢他的 markdown 样式&#xff0c;尤其是代码块高亮的样式。当然用 vscode 大家基本上都会选择安装一个Markdown-preview-enhanced的插件&#xff0c;这个插件的确…

【DDD】领域驱动设计总结——如何构造领域模型

文章目录 一 分离领域二 领域对象分类2.1 实体(ENTITY)2.2 值对象(VALUE OBJECT)2.3 服务(SERVICE)2.4 模块&#xff08;&#xff2d;ODULE&#xff09; 三 管理领域对象的生命周期3.1 聚合&#xff08;AGGREGATE&#xff09;3.2 工厂&#xff08;FACTORY&#xff09;3.3 存储库…

mysql:免费的GUI客户端工具推荐并介绍常用的操作

给大家推荐几个常用的 mysql 数据库客户端 sequel-pro sequel-ace 官网下载地址 免费 sequel-ace 可以理解为 Sequel Pro 的升级版&#xff0c;由于Sequel Pro官方不维护了&#xff0c;特别是对 MySQL 8.0 支持不好&#xff0c;所以现在由社区维护了新分支 sequel-ace&#x…

具备这四个特征的项目经理,牛逼!

大家好&#xff0c;我是老原。 成为一个业绩第一又能准时下班的工作强人&#xff0c;应该是每个职场人的梦想&#xff0c;但现实往往不那么尽如人意…… 虽然如此&#xff0c;但是不代表我们不能向能做到这样的大佬看齐啊。 工作十余年&#xff0c;见过各种各样的职场人士&a…

C++——解锁string常用接口

目录 string::npos; 1.测试string容量相关的接口&#xff1a; 1.1 string::size() 1.2 string::clear() 1.3 string::resize() 1.4 string::erase() 1.5 string::reserve() 保留 1.6 std::string::shrink_to_fit 2.string数据插入删除相关的接口 2.1 std::string::pus…

数据结构学习笔记(王道)

数据结构学习笔记&#xff08;王道&#xff09; PS&#xff1a;本文章部分内容参考自王道考研数据结构笔记 文章目录 数据结构学习笔记&#xff08;王道&#xff09;一、绪论1.1. 数据结构1.2. 算法1.2.1. 算法的基本概念1.2.2. 算法的时间复杂度1.2.3. 算法的空间复杂度 二、…

Java封装讯飞星火大模型历险记

问题描述与分析 现状描述与目标 在使用讯飞星火大模型API的过程中&#xff0c;API的返回结果在可以在其他线程中进行分次打印&#xff0c;但是在main方法中直接打印返回结果&#xff0c;显示为空。这种情况下不利于二次封装&#xff0c;希望在main方法中获取完整的API返回结果…