方法一:顺序遍历计数,时间复杂度O(n)
方法二:二分搜索+“中心向两边”遍历,时间复杂度O(logn)+O(n)=O(n)
public int GetNumberOfK(int [] array , int k) {
int i,j,pos;
pos = getK(array , k);
if(pos==-1)
return 0;
i=pos;j=pos;
//下标条件判断一定要与的前面,防止数组下标越界
while(i>=0 && array[i]==k ) i--;
while(j<array.length && array[j]==k) j++;
return j-i-1;//下标多移了一步,所以j-1-(i+1)-1=j-i-1
}
public int getK(int [] array , int k){
int low = 0, high = array.length-1;
int mid = (low + high)/2;
while(low <= high){
if(k > array[mid]){
low = mid + 1;
}else if(k < array[mid]){
high = mid - 1;
}else{
return mid;
}
mid = (low + high)/2;//mid的计算不能放在if语句中,否则死循环
}
return -1;
}
方法三:完全二分搜索,分别找重复元素的头和尾,时间复杂度O(2logn)=O(logn)
public int GetNumberOfK(int[] array , int k) {
int i = getFirstK(array,k,0,array.length-1);
int j = getLastK(array,k,0,array.length-1);
if(i!=-1&&j!=-1)
return j-i+1;
return 0;
}
public int getFirstK(int[] array , int k, int low, int high){
int mid = (low + high)>>1;
while(low <= high){
if(k > array[mid]){
low = mid + 1;
}else if(k < array[mid]){
high = mid - 1;
}else if(mid-1>=0 && array[mid-1]==k){// 找“头”
high = mid - 1;
}else{
return mid;
}
mid = (low + high)>>1;
}
return -1;
}
public int getLastK(int[] array , int k, int low, int high){
int mid = (low + high)>>1;
while(low <= high){
if(k > array[mid]){
low = mid + 1;
}else if(k < array[mid]){
high = mid - 1;
}else if(mid+1<array.length && array[mid+1]==k){// 找“尾”
low = mid + 1;
}else{
return mid;
}
mid = (low + high)>>1;
}
return -1;
}