package June;
public class 统计数在排序数组中出现次数 {
public int GetNumberOfK(int[] array, int k) {
/* //最简单,一次循环遍历
int count=0;
for(int i=0;i<array.length;i++){
if(array[i]==k){
count++;
}
}
return count;*/
//二分查找算法,因为是排序好的,在数据大的情况下,这种算法更优
//若K出现多次,则查找数组中K最左侧的下标,再查找数组中K最右侧下标,相减得出次数,
//这种算法,比一次遍历要快
if(array.length==0) return 0;
int FirstKey=getFirstKey(array,k,0,array.length-1);
int LastKey=getLastKey(array,k,0,array.length-1);
if(FirstKey!=-1&&LastKey!=-1)
return LastKey-FirstKey+1;
return 0;
}
//递归二分查找,返回-1说明没有找到,返回最左侧K下标
private int getFirstKey(int []array,int k,int begin,int end){
//一次没有找到K的情况
if(begin>end) return -1;
int middle=(begin+end)/2;
//左侧
if(k<array[middle]){
return getFirstKey(array,k,begin,middle-1);
}//右侧
else if(k>array[middle]){
return getFirstKey(array, k, middle+1, end);
}//找到一个相等的,则往左边继续查找,直到找到最左边的一个K
else if(middle-1>=0&&array[middle-1]==k){
return getFirstKey(array, k, begin, middle-1);
}//左侧没有,找到的是当前最左侧的K
else{
return middle;
}
}
//循环二分查找
private int getLastKey(int []array,int k,int begin,int end){
if(begin>end) return -1;
int middle;
while(begin<=end){
middle=(begin+end)/2;
if(k<array[middle]){
end=middle-1;
}else if(k>array[middle]){
begin=middle+1;
}
//找到一个相等的,往右侧继续查找
else if(middle+1<array.length&&k==array[middle+1]){
begin=middle+1;
}
// 当前最右侧
else{
return middle;
}
}
return -1;
}
}