题目:统计一个数字在排序数组中出现的次数。
分析:因为是排序数组,肯定想到的是二分查找,使用二分查找找到第一次和最后一次数字k的位置,即可统计出出现的次数。
package Solution25;
//统计一个数字在排序数组中出现的次数。
public class Solution {
//由于数组有序,所以使用二分查找方法定位k的第一次出现位置和最后一次出现位置
public int GetNumberOfK(int [] array , int k) {
if(array.length<=0 ||array==null ) return 0;
int first=GetFirstK(array,0,array.length-1,k);
int end = GetLastK(array,0,array.length-1,k);
if(first!=-1 && end!=-1)
return end-first+1;
return 0;
}
//递归写法
public int GetFirstK(int[] array,int start,int end ,int k){
if(start>end){
return -1;
}
int mid=(start+end)/2;
if(array[mid]>k){
return GetFirstK(array,start,mid-1,k);
}else if(array[mid]<k) {
return GetFirstK(array, mid + 1, end, k);
}
//此时大前提是array[mid]==k,判断mid是否为第一个k的位置需要看mid-1是否为k
else if(mid-1>=0 && array[mid-1]==k){
return GetFirstK(array,start,mid-1,k);
}else{
return mid;
}
}
//非递归写法
public int GetLastK(int[] array,int start,int end,int k){
int len=array.length;
int mid;
while(start<=end){
mid=(start+end)>>1;
if(array[mid]>k){
end=mid-1;
}else if(array[mid]<k){
start=mid+1;
}
//此时大前提是array[mid]==k,判断mid是否为最后一个k需要看mid+1是否为k
else if( mid+1<len && array[mid+1]==k){
start=mid+1;
}else{
return mid;
}
}
return -1;
}
public static void main(String[] args) {
Solution s=new Solution();
int []arr={3,3,3,3,4,5};
System.out.println(s.GetNumberOfK(arr,3));
}
}
值得注意的是,在第26、44行处判断是否是第一个k和是否是最后一个k时,分别需要往前和往后一位看是否仍为K,此时判断的条件mid-1>=0 和 mid+1<length应放在判断语句最前,然后再去判断该位置是否为K,否则会数组越界错误。
时间复杂度为logn。