来自:http://www.acmerblog.com/ubiquitous-binary-search-5345.html
我们都知道二分查找算法,实际上二分查找以及其扩展应用是很广泛的。这里收集了一些和二分查找有关的有趣问题。强烈建议大家看完问题后最小化浏览器,先尝试自己去解决,然后再看代码,问题都不是太难。
问题1描述
给一个已经排序的数组,其中有N个互不相同的元素。要求使用最小的比较次数找出其中的一个元素。(你认为二分查找在排序数组里找一个元素是最优的算法的吗?)
不需要太多的理论,这是一个典型的二分查找算法。先看下面的代码:
1 // 返回要查找元素的下标,-1为没有找到 2 int BinarySearch(int A[], int l, int r, int key) 3 { 4 int m; 5 while( l <= r ) 6 { 7 m = l + (r-l)/2; 8 9 if( A[m] == key ) //第一次比较 10 return m; 11 12 if( A[m] < key ) // 第二次比较 13 l = m + 1; 14 else 15 r = m - 1; 16 } 17 18 return -1; 19 }
理论上,我们最多需要 logN+1 次比较。仔细观察,我们在每次迭代中使用两次比较,除了最后比较成功的一次。实际应用上,比较也是代价高昂的操作,往往不是简单的数据类型的比较。减少比较的次数也是优化的方向之一。
下面是一个比较次数更少的实现:
1 // 循环不变式: A[l] <= key & A[r] > key 2 // 边界: |r - l| = 1 3 // 输入: A[l .... r-1] 4 int BinarySearch(int A[], int l, int r, int key) 5 { 6 int m; 7 while( r - l > 1 ) 8 { 9 m = l + (r-l)/2; 10 11 if( A[m] <= key ) 12 l = m; 13 else 14 r = m; 15 } 16 if( A[l] == key ) 17 return l; 18 else 19 return -1; 20 }
在while循环中,我们仅依赖于一次比较。搜索空间( l->r )不断缩小,我们需要一个比较跟踪搜索状态。
需要注意的,要保证我们恒等式(A[l] <= key & A[r] > key)正确,后面还会用到循环不变式。
自己可以实现一下:
1 #include <stdio.h> 2 #include <math.h> 3 #include <queue> 4 #include <vector> 5 #include <stack> 6 #include <map> 7 #include <string> 8 #include <string.h> 9 #include <algorithm> 10 #include <iostream> 11 using namespace std; 12 int binarysearch(int a[],int l,int r,int k){ 13 int mid; 14 while(r-l>1){ 15 mid=(r+l)/2; 16 if(a[mid]<=k) 17 l=mid; 18 else 19 r=mid; 20 } 21 if(a[l]==k) 22 return l; 23 else 24 return -1; 25 } 26 int main() 27 { 28 int a[10]; 29 int n,m,i,j; 30 for(int i=0;i<5;i++){ 31 cin>>a[i]; 32 } 33 sort(a,a+5); 34 scanf("%d",&n); 35 m=binarysearch(a,0,5,n); 36 if(m!=-1) 37 printf("%d\n",a[m]); 38 else 39 cout<<"NO"<<endl; 40 return 0; 41 }
时间: 2024-10-10 13:04:33