题意
统计一个数字在排序数组中出现的次数。
做法
二分,本道题有总巧妙的想法: 找出第一个大于 k -0.5 ,和第一个大于 k + 0.5 的位置。后面减前面即可。
public int GetNumberOfK(int [] array , int k) {
if(array == null || array.length == 0)
return 0;
return biSearch(array, k + 0.5) - biSearch(array, k - 0.5);
}
int biSearch(int[] array, double k) {
// 二分找到第一个大于 k 的位置
int l = 0, r = array.length-1, mid;
while (l <= r){
mid = (l + r) >> 1;
if(array[mid] > k){
r = mid-1;
}else if(array[mid] < k){
l = mid+1;
}
}
return l;
}
其他变种
二分的原则是
1)while(l<=r)
2)每一个if ()判断分支 要么 l = mid + 1 ,要么 r = mid - 1。 否则如果有l = mid ,那么当 l == r的时候就会死循环。
找出第一个等于k的位置
例如 : 1 2 3 3 3 4 ,返回 2
思路:等于符号应该加在r = mid-1的条件上,保证了r指的位置是小于k的位置。条件截至的时候必定是 l == r,那么此时 arr[ l ] < k ,l++。 返回l就得到第一个等于k的位置了。
int biSearch(int[] array, double k) {
int l = 0, r = array.length-1, mid;
while (l <= r){
mid = (l + r) >> 1;
if(array[mid] >= k){
r = mid-1;
}else if(array[mid] < k){
l = mid+1;
}
}
return l;
}
找出第一个小于k的位置
如果看懂了上一个的分析,那么这个就很简单了,返回r即可