问题引入:
给定一个按照升序排列的长度为n的整数数组,询问元素k,返回k在数组中的起始位置和终止位置。
如果数组中不存在该元素,则返回“-1 -1”。
例如:
6 3
1 2 2 3 3 4
则应返回4 5
二分最重要的一步是区间划分,即确定左区间表示什么,右区间表示什么,然后确定是输出l还是r
对于本题,
求起始位置时,可以让>=k的元素划分到右区间,最后起始位置start=r
求终止位置时,可以让<=k的元素划分到左区间,最后终止位置end=l
const int N = 1e5+5;
int n,a[N];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
int start,end;
int l=0,r=n+1;//一开始让l指针与r指针指在待划分区间[1,n]的两侧
while(l+1!=r)
{
int mid=(l+r)/2;
if(a[mid]>=k) r=mid;
else l=mid;
}
start=r;
l=0,r=n+1;
while(l+1!=r)
{
int mid=(l+r)/2;
if(a[mid]<=k) l=mid;
else r=mid;
}
end=l;
if(start<=end) cout<<start<<" "<<end<<endl;
else cout<<-1<<" "<<-1<<endl;
return 0;
}
浮点数的二分:
给定一个浮点数x(-10000<=x<=10000),求它的三次方根。(结果保留6位小数)
int main()
{
double x; cin>>x;
double l=-100-1,r=100+1;
while(r-l>1e-7)//注意精度问题,此处最少要1e-7
{
double mid=(l+r)/2;
if(mid*mid*mid>=x) r=mid;
else l=mid;
}
printf("%.6lf\n",l);
return 0;
}