題目描述:
統計一個數字在排序數組中出現的次數。例如,輸入排序數組{1,2,3,3,3,3,4,5}和數字3,由於數字3在該數組中出現了4次,所以函數返回4。
解題思路:
既然輸入的數組是有序的,所以我們就能很自然的想到用二分查找算法。以題目中給的數組為例,一個比較自然的想法是用二分查找先找到一個3,由於要計算的是輸出的次數,所以需要在找到的這個3的左右兩邊分別再進行順序掃描,進而得到3的個數,這樣最壞的情況下時間復雜度仍然是O(n),和直接順序掃描的效率相同。
因此,需要考慮怎樣更好的利用二分查找算法,由於數組有序,如果知道了第一個k出現的位置和最后一個k出現的位置,那么我們就可以直接算出有多少個k。因此將思路轉化為通過二分查找求第一個和最后一個k出現的位置。
以第一個k出現的位置為例,利用二分查找算法可以直接對數組進行二分,而每次總是拿中間的數字和k做比較,如果中間的數字大於k,那么第一個k只有可能出現在左邊,下一次直接在數組左半段繼續進行二分查找;如果中間的數字小於k,則第一個k只有可能出現在右邊,則在右半段再查找;如果中間的數字等於k,我們先判斷它前面的一個數字是不是k,如果不是,那么這個中間的數字就是第一個出現的位置,反之,如果中間數字前面的數字是k,那么第一個k仍然在前半段,繼續查找。
同理,找最后一個k出現的位置方法類似,可以使用兩個函數分別獲得。
編程實現(Java):
public class Solution {
public int GetNumberOfK(int [] array , int k) {
int first=getFirstIndex(array,k);
int last=getlastIndex(array,k);
if(first==-1 || last==-1)
return 0;
return last-first+1;
}
//二分查找
public int getFirstIndex(int[] array,int k){
int res=-1;
if(array==null||array.length==0)
return res;
int low=0,high=array.length-1;
while(low<=high){ //要有=
int mid=low+(high-low)/2;
if(array[mid]<k)
low=mid+1;
else if(array[mid]>k)
high=mid-1;
else { //相等
mid=mid-1;
if(mid<low || array[mid]!=k)
return mid+1;
else
high=mid;
}
}
return res;
}
public int getlastIndex(int[] array,int k){
int res=-1;
if(array==null||array.length==0)
return res;
int low=0,high=array.length-1;
while(low<=high){ //要有=
int mid=low+(high-low)/2;
if(array[mid]<k)
low=mid+1;
else if(array[mid]>k)
high=mid-1;
else { //相等
mid=mid+1;
if(mid>high || array[mid]!=k)
return mid-1;
else
low=mid;
}
}
return res;
}
}