upper_bound函数,binary_check函数
个人心得:二分的经典运用,刚开始就是upper_bound可能难以实现一点,还有就是要注意没找到的时候
lower_bound 返回大于等于key的第一个元素的下标。
upper_bound 返回大于key的第一个元素的下标(即小于等于key的最后一个元素的下一个元素的下标)。
设result为这两个函数的返回值。
在每次的while迭代前,result的候选范围为区间[low,high]。
初始情况:这两个函数的返回值的可能范围为[0,n](数组A的下标范围是[0,n-1])。
保持:根据A[middle]和key的比较,有3种情况:
①A[middle]=key
对于lower_bound,A[middle](及其前面的元素)可能是等于key的第一个元素,而A[middle+1]至少是等于key的第二个元素。故middle为候选result,而middle+1不是。故令high=middle。
对于upper_bound,A[middle]可能是小于等于key的最后一个元素,而A[middle]前面的元素则不可能,故它的下一个元素A[middle+1]可能是大于key的第一个元素。故令low=middle+1。
若数组A中不存在与key相等的元素,那么两个函数的result是一样的,即都是大于key的第一个元素的下标,所以在A[middle]和key不相等的情况下,对low和high的设置是一样的。
②A[middle]<key
而A[middle+1]有可能大于key,且A[middle]之前的元素不可能大于key。故令low=middle+1。
③A[middle]>key
A[middle]有可能是大于key的第一个元素,而A[middle+1]至少是第二个,且A[middle]之前的元素也可能大于key,故令high=middle。
终结:
每次区间[low,high]的长度都会至少减1。当长度减少至1时,结果就出来了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iomanip> 6 #include<algorithm> 7 using namespace std; 8 int uppercheck(int a[],int n,int key) 9 { 10 int i=0,j=n-1; 11 while(i<j){ 12 int mid=(i+j)/2; 13 if(a[mid]>key) 14 j=mid; 15 else 16 i=mid+1; 17 } 18 if(a[i]>key) 19 return i; 20 else return -1; 21 } 22 int binarycheck(int a[],int n,int key) 23 { 24 int i=0,j=n-1; 25 while(i<=j){ 26 int mid=(i+j)/2; 27 if(a[mid]==key) 28 return mid; 29 else if(a[mid]>key) 30 j=mid-1; 31 else 32 i=mid+1; 33 } 34 return -1; 35 } 36 int main() 37 { 38 39 int a[15]; 40 for(int i=0;i<5;i++) 41 cin>>a[i]; 42 cout<<binarycheck(a,5,5)<<endl; 43 cout<<uppercheck(a,5,5)<<endl; 44 return 0; 45 }