二分
哈罗,大家好,我是cht。
前两天好不容易才弄懂二分,现在跟大家分享一下。
二分的思路
从前有这么一道题,说:
如何用10个砝码撑出1-1023的重量?
大家仔细考虑下这题,相信大家都已经有答案了。
1,2,4,8,16,32,64,128,256,512这十个砝码。
再来一题:
有一栋高楼,怎么用最少的次数知道它最多在几层被抛下是不会碎?
答案就是是二分。
好,接下来我们步入正轨,到底什么是二分?
请看图:
这就是二分,一次可以排除几乎一半的答案。
所以我个人觉得二分就是枚举的一种优化。
先让大家看看二分有多nb。
假设共有一亿种答案,二分算30来此也就够了!
不信的童鞋们算算1024乘1024乘1024
接下来说说二分的两种情况
情况1:整数二分
整数二分就是整数情况下的二分,比较难做。
情况2:浮点数二分
浮点情况的二分,几行搞定!
下面是模板
1、整数二分模板1
int l = 0, r = n - 1;
while(/*......*/)//条件,因题而异
{
int mid = l + r >> 1;
if(/*......*/) r = mid;//中间为符不符合条件(写>=)
else l = mid + 1;
}
cout <</*......*/ << l << /*......*/;
2、整数二分模板2
int l = 0, r = n - 1;
while(/*......*/)//条件,因题而异
{
int mid = l + r + 1 >> 1;//注意要加1!!!
if(/*......*/) l = mid;//中间为符不符合条件(写<=)
else r = mid - 1;
}
cout <</*......*/ << l << /*......*/;
3、浮点数二分模板(其实和上面一样)
double l = /*......*/,r = /*......*/;
while(/*......*/)
{
double mid = (l + r) / 2;
if(/*......*/) r = mid;
else l = mid;
}
printf("%.*lf\n", l)//*代表保留几位小数
最后来两道题(选自算法基础课)
1、数的范围
题目描述
给定一个按照升序排列的长度为n的整数数组,以及 q 个查询。
对于每个查询,返回一个元素k的起始位置和终止位置(位置从0开始计数)。
如果数组中不存在该元素,则返回“-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()
{
cin >> n >> m;
for(int i = 0; i < n; i ++) cin >> q[i];
while(m --)
{
int x;
cin >> x;
int l = 0, r = n - 1;
while(l < r)
{
int mid = l + r >> 1;
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 >> 1;
if(q[mid] <= x) l = mid;
else r = mid - 1;
}
cout << l << endl;
}
}
return 0;
}
2、数的三次方根
题目描述
给定一个浮点数n,求它的三次方根。
数据范围
−10000≤n≤10000
样例
输入样例:
1000.00
输出样例:
10.000000
代码
#include<iostream>
using namespace std;
int main()
{
double x;
cin >> x;
double l = -10000,r=10000;
while(r - l > 1e-8)
{
double mid = (l + r) / 2;
if(mid * mid * mid >= x) r = mid;
else l = mid;
}
printf("%lf", l);
return 0;
}
用那个不用考虑边界的板子会不会更好
整数二分一直有一个问题搞不明白,二分最后如果找到结果应该是left对应的值还是right对应的值,还是每道题都必须自己分析呢?
关于最后的答案是需要自己分析,y总建议画图hh
有一种比较傻瓜一点的模板是while(left + 1 < right), 结束以后分别判断left和right是否符合题意就可以,可以把两个二分的模板合二为一
对的
还有您真的是产品经理?wow
未来。。。也可以叫做将来,等同于future
wowowow
%%%%%%%%%%%%%%%%%
???
您tql
我回来了
话说tql是什么意思
太强了???
太强了
哦哦