二分
二分
二分查找是一种思路很简单,但是细节很复杂的算法。尤其是一些边界问题。使用二分需要确定一下两点:

整数二分

特点离散化,答案必在上述两个位置之一。
1.答案是红色区间的右端点

Q:为什么红线部分要加1?
A:这是由于除法会自动向下取整。例如:L=4 R=5 时,M = (4+5)/ 2 = 4=L,L = M = L,L、R永远不变,陷入死循环。
不加1:

加1:

2.答案是绿色区间的左端点

Q:为什么这里要补加1?
同理如下图:


小结

数字的范围
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 100000;
int n,q;
int s[N+5];
int main(){
scanf("%d%d",&n,&q);
for (int i = 0; i < n; i ++ ) scanf("%d",&s[i]);
while(q--)
{
int k = 0;
scanf("%d",&k);
int l = 0, r = n - 1;
while(l < r)
{
int m = (l + r) / 2;
if (s[m] >= k) r = m;
else l = m + 1;
}
if (s[l] == k)
printf("%d ",l);
else
printf("-1 -1\n");
r = n - 1;
while(l < r)
{
int m = l + r + 1 >> 1;
if (s[m] <= k)
l = m;
else r = m - 1;
}
if (s[l] == k)
printf("%d\n",l);
}
return 0;
}
实数二分


数的三次方根
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main(){
double n;
scanf("%lf",&n);
double l = -10000,r = 10000;
while (r - l > 1e-8 )
{
double mid = (l + r) / 2;
if (mid * mid * mid >= n) r = mid;
else l = mid;
}
printf("%.6f",l);
return 0;
}
习题


浙公网安备 33010602011771号