题目描述
二分法思想
前提:数据是有序的
比较这组数据中间的那个数与要查找的数的大小,根据比较结果缩小比较区间,当比较区间为1时即锁定我们要查找的数
题解
第一步:确定要查找的数(该数在数组中可能有多个)是左边界(第一个x)还是右边界(第二个x)
第二步:选对应的二分模板
1)查找左边界
比较区间的中间值与x的大小,若中间值大于等于x则将r=mid区间缩小一半,否则l=mid+1,循环上面步骤,直到l=r。此时区间长度为1,覆盖的那唯一一个数就是我们要查找的x。
对应模板:
while(l<r)
{
int mid = l+r >> 1;
if(q[mid]>=x) r = mid;
else l = mid+1;
}
2)查找右边界
右边界x左边的数全小于等于x,则此时判断条件为q[mid]<=x
注意:此时mid=l+r+1>>1,因为若mid任为区间一半,则会发生死循环
比较区间的中间值与x的大小,若中间值小于等于x则将l=mid区间缩小一半,否则r=mid-1,循环上面步骤,直到l=r。此时区间长度为1,覆盖的那唯一一个数就是我们要查找的右边界x
对应模板:
while(l<r)
{
int mid = l+r+1 >> 1;
if(q[mid]<=x) l = mid;
else r = mid-1;
}
完整代码
#include<stdio.h>
#define N 100001
int bsearch_left(int l, int r, int x);
int bsearch_right(int l, int r, int x);
int q[N];
int main(void)
{
int n,m,i,x; scanf("%d",&n); scanf("%d",&m);
for(i=0; i<n; i++) scanf("%d",&q[i]);
while(m--)
{
scanf("%d",&x);
int l = 0, r = n-1;
l = bsearch_left(l,r,x);
if(q[l]!=x)
{
l = -1; printf("%d %d\n",l,l);
}
else
{
printf("%d ",l);
l = 0, r= n-1;
l = bsearch_right(l,r,x);
printf("%d\n",l);
}
}
return 0;
}
int bsearch_left(int l, int r, int x)
{
while(l<r)
{
int mid = l+r >> 1;
if(q[mid]>=x) r = mid;
else l = mid+1;
}
return l;
}
int bsearch_right(int l, int r, int x)
{
while(l<r)
{
int mid = l+r+1 >> 1;
if(q[mid]<=x) l = mid;
else r = mid-1;
}
return l;
}