1.引言
问题:A心里想一个1-1000之间的数,B来猜,可以问问题,A只能回答是或否。怎么猜才能问的问题最少?
- 是1吗?是2吗?…是999吗?这样猜平均要问500次
- 大于500吗?大于750吗?大于625吗?…每次缩小猜测范围到上次的一半,只需要10次
这样就得出了我们的二分算法,二分算法就是每次缩小一半的范围来确定查找的数值,这样会节省查找时间,优化算法。
二分算法有一个条件就是在查找区间内需要保证数据有序排列
2. 二分查找函数
- 写一个函数BinarySerch,在包含size个元素的、从小到大排序的int数组a里查找元素p,如果找到,则返回元素下标,如果找不到,则返回-1,要求复杂度o(log(n))
int BinarySearch(int a[],int size,int p)
{
int L;//查找区间的左端点,用下标表示
int R=size-1;//查找区间的右端点
while(L<=R){//如果查找区间不为空就继续查找
int mid=L+(R-L)/2;//这里为了防止(R+L)/2 溢出 取查找区间正中元素的下标
if(a[mid]==p){
return mid;
}
else if(a[mid]>p){
R=mid-1;//设置新的查找区间的右端点
}
else if(a[mid]<P){
R=mid+1;//设置新的查找区间的左端点
}
return -1;//没有找到,返回-1
}
}
- 写一个函数LowerBound,在包含size个元素的、从小到大排序的int数组a里查找比给定整数p小的,下标最大的元素。找到则返回其下标,找不到返回-1
int LowerBound(int a[],int size,int p)
{
int L=0;//查找区间的左端点
int R=size-1;//查找区间的右端点
int lastPos=-1;//到目前为止找到的最优解
while(L<=R)//如果查找区间不为空就继续查找
{
int mid=L+(R-L)/2;//取查找区间正中元素的下标
if(a[mid]>=p)
{
R=mid-1;
}
else{
lastPos=mid;
L=mid+1;
}
}
return lastPos;
}
3.例题
例题一:找一对数
题目描述: