題目:統計一個數字在排序數組中出現的次數。例如輸入排序數組爲面試
{1,2,3,3,,3,3,4,5}和數字3,因爲3在這個數組中出現了4次,所以輸出4算法
既然輸入的數組是排序的,那麼咱們很天然的想到利用二分查找算法。在 題目給出的例子中,咱們能夠先用二分查找算法找到第一個3.因爲3可能出現屢次,所以咱們找到的3的左右兩遍可能都是3,因而咱們在找到3的左右兩邊順序 掃描,分別找出第一個3和最後一個3.由於要查找的數字在長度爲n的數組中可能很出現O(n)次,因此順序掃描的時間複雜度爲O(n)。所以這種算法的效 率和直接從頭至尾順序掃描整個數組統計3出現的次數的方法是同樣的。顯然,面試官是不會滿意這種算法,它會提示咱們還有更快的算法。數組
接下來咱們思考如何更好的利用二分查找算法。假設咱們統計數字k在排序數組中出現的次數。在前面的算法的時間主要消耗在如何肯定重複出現的第一個k和最後一個k的位置上,有沒有能夠利用的二分查找算法直接找到第一個k和最後一個k。排序
咱們先分析如何利用二分查找在數組中找到第一個k,二分查找算法老是 先拿數組的中間的數字和k作比較。若是中間的數字比k大,那麼k只能出如今數組的前半段,下一輪咱們旨在數組的前半段查找就能夠了。若是中間的數字比k 小,那麼k只能出如今數組的後半段,下一輪咱們只在數組的後半段查找就能夠了。若是中間的數字和k相等呢?咱們先判斷這個數字是否是第一個k。若是位於中 間數字的前面一個數字不是k,此時中間的數字恰好就是第一個k。若是中間的數字的前面一個數字也是k,也就是說第一個k確定在數組的前半段,下一輪咱們仍 然須要在數組的前半段查找。遞歸
同理咱們利用上面的思路找到最後一個k。get
找到第一個k和最後一個k後就能夠知道k出現的次數了,ast
實現代碼以下:class
package cglib;test
public class jiekou {方法
//遞歸找到排序數組中第一個k
private int getFirstK(int[] arr,int k,int left,int right){
if(left > right)
return -1;
int middleIndex = (left+right)/2;
int middleData = arr[middleIndex];
if(middleData == k){ //若是中位數等於k
if((middleIndex >0 && arr[middleIndex -1]!=k)|| middleIndex == 0)
return middleIndex; //中位數是第一個k
else
right = middleIndex -1; //中位數不是第一個k,則往中位數左邊找第一個k
}
else if(middleData > k)//中位數大於k ,則第一個k確定在中位數左邊
right = middleIndex -1; //往中位數左邊找第一個k
else
left = middleIndex +1; //中位數小於k ,則第一個k確定在中位數右邊
return getFirstK(arr,k,left,right); //遞歸
}
//相同的思路,遞歸找到最後的一個k
private int getLastK(int[] arr,int k,int left,int right){
if(left > right)
return -1;
int middleIndex = (left + right)/2;
int middleData = arr[middleIndex];
if(middleData == k){
if((middleIndex <arr.length -1 && arr[middleIndex+1]!=k) || middleIndex ==arr.length-1)
return middleIndex;
else
left = middleIndex+1; //中位數不是最後一個k,則往中位數右邊找最後個k
}
else if(middleData <k){//中位數小於k,則往中位數右邊找最後一個k
left = middleIndex +1;
}else
right = middleIndex -1; //中位數大於k,則往中位數左邊找最後一個k
return getLastK(arr,k,left,right); //遞歸
}
//計算出k在數組中出現的次數
public int getNumberOfK(int[] arr,int k){
int number = 0;
if(arr.length >0){
int first = getFirstK(arr,k,0,arr.length-1);
int last = getLastK(arr,k,0,arr.length -1);
if(first >-1 && last >-1)
number =last-first+1;
}
return number;
}
public static void main(String[] args){
int[] arr= {1,2,3,3,3,3,4,5};
jiekou test = new jiekou();
System.out.println(test.getNumberOfK(arr, 3));
}
}
輸出:4