问题:计一个数字在排序数组中出现的次数
如: 整数数组arr,数组中元素的个数是n,数组arr已经排好序,要在arr中找到某个某个整数x出现的次数,比如arr[] = {1,2,2,3,5,10},找到2的出现次数就是2。
问题分析:相必看到有序数组的字样,想到利用二分应该是很顺利成章的事了。我们可以利用二分搜索求出x在arr中出现的第一个位置lo和最后一个位置hi,然后计算hi-lo+1的值就是x在arr出现的次数了,当然也有可能x并没有在arr中出现过,这时hi和lo都等于-1。时间复杂度是两个二分的复杂度:2*O(log n)。
/************************************************************************/ /* 10、在排序数组中,找出给定数字出现的次数 */ /************************************************************************/ //二分查找,二分查找key第一次出现的位置,二分查找最后一次出现的key //返回两者相减+1或者找到第一次出现的位置,向后查找 int binarySearchFirstPos(int * iArr, int l, int h, int key) { while(l <= h ) { int mid = (l + h) / 2; if(iArr[mid] < key) l = mid +1; else if(iArr[mid] > key) h = mid - 1; else { if(mid == l || iArr[mid - 1] != key) return mid; else h = mid - 1; } } return -1; } int binarySearchLastPos(int * iArr, int l, int h, int key) { while(l <= h) { int mid = (l + h) / 2; if(iArr[mid] < key) l = mid + 1; else if(iArr[mid] > key) h = mid - 1; else { if(mid == h || iArr[mid + 1] != key) return mid; else l = mid + 1; } } return -1; } int numOfKey(int * iArr, int length, int key) { int firstPos = binarySearchFirstPos(iArr, 0, length - 1, key); int lastPos = binarySearchLastPos(iArr, 0, length - 1, key); cout << firstPos << " " << lastPos << endl;; if(firstPos == -1) return 0; else return lastPos - firstPos + 1; }
可以看以前写的文章二分法的变异,自己写的另外代码:
#include<iostream> using namespace std; int searchFirstEqual(int a[],int n,int key) { int low=0,high=n-1,mid; while(low<=high) { mid=(low+high)>>1; if(a[mid]>=key) high=mid-1; else low=mid+1; } if(low<n && a[low]==key) return low; else return -1; } int searchLastEqual(int arr[],int n,int key) { int low=0,high=n-1,mid; while(low<=high) { mid=low+(high-low)/2; if(arr[mid]<=key) { low=mid+1; } else { high=mid-1; } } if(high>=0 && arr[high]==key) return high; else return -1; } int main() { int a[]={1,3,3,3,5,6}; int n=sizeof(a)/sizeof(a[0]); int start=searchFirstEqual(a,n,3); int end=searchLastEqual(a,n,3); cout<<start<<endl; cout<<end<<endl; cout<<end-start+1<<endl; }