您的位置:首页 > 编程语言

编程珠玑第9章二分搜索(有重复数字)中查找某数出现的第一个位置

2013-08-21 09:49 531 查看
binary search:search the first occurence of a number

查找的数中有重复的数

只需在原始的二分搜索基础上进行修改,当中间的数A[mid]与target值相同时,target值的第一次出现要么是在mid处,要么是在mid左边。若low与mid(low==mid)的闭区间只包含一个数,则返回值为mid,若low<mid,则修改high为mid

具体实现如下

#include<iostream>
using namespace std;

int binary_search(int A[],int target,int low,int high){
while(low<=high){
int mid=(low+high)/2;
if(target<A[mid])
high=mid-1;
else if(target>A[mid])
low=mid+1;
else if(low<mid)//&&target==A[mid]
high=mid;
else //mid==low
return mid;
}
return -1;
}
int main(){
int A[]={1,2,3,3,5,6,7,9};
cout<<binary_search(A,3,0,7)<<endl;
int B[]={1,2,3,3,4,4,7};
cout<<binary_search(B,4,0,6)<<endl;
return 0;
}


编程珠玑上Column 9给出了另外一个解法。

首先虚拟出两个数组元素,x[-1],x
,n为数组的size,实际上这两个元素不存在,循环时不变量是x[l]<t<x<=x[u]

这与一般二分搜索假设的范围有点不一样。因为l初始为-1,u初始为n,该条件初始时候成立,实际上这两个虚拟的元素在代码中未使用

invariant在循环中保持。

因为初始时u>=l+2

m>=l+1

l<=u-2

所以l+1<=m<=u-1

所以l<m<u

根据循环中的语句l<u在循环中是得到保持的

l=-1; u=n

while(l+1!=u){
/*invariant :x[l]<t &&x[u]>=t &&l<u*/
int m=(l+u)/2;
if(x(m)<t)
l=m;
else
u=m;
}

p = u ;
/*assert l+1==u&&x[l]<t&&x[u]>=t*/
if(p>=n || x[p]!=t)
p=-1


关于编程珠玑中9.3中的代码

if p>1000|| x[p] !=t

p=-1

这里的条件p>1000应该改为p>=1000,因为p=1000的时候,数组已经越界了。

实际上该算法算出的p是可能等于1000。因为要使p=1000,那么目标值t肯定处于后半区别,即l=1000-512

l+i=1000,处在[1000-512,1000]的区间之内。而l的更新必定遵循l=1000-512+256+128+...+1的规律,该数必定是个奇数,l最大可能的值是1000-512+256+128+64+32+16+8+4+2+1=999而p=l+1=1000,这时求出的p是可能等于1000的,所以这里写成p>1000是不行的

9.3最后一个版本代码是循环展开之后的版本。

第7题求解某数的二进制序列中1的个数

int count =0;

while(x>0){

x=x&(x-1);

count++;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐