題目:
統計一個數字在排序數組中出現的次數。例如輸入排序數組{1,2,3,3,3,3,4,5}和數字3,由於3在這個數組中出現了4次,因此輸出4.
最直接的做法:先用二分查找算法找到一個3,由於3可能出現多次,因此我們找到的3的左右兩邊可能都有3,於是在找到的3左右兩邊順序掃描,分別找到第一個3和最後一個3。因爲要查找的數字在長度爲n的數組中有可能出現O(n)次,因此這種算法的效率和直接從頭到尾掃描整個數組統計3出現的次數的方法相同。
如何更好地利用二分查找算法?
利用二分查找算法找到數組中第一個k和最後一個k的位置。
1、找到第一個k
首先利用二分查找,找到k,判斷位於該k前面的一個數字是否爲k,如是,則繼續在數組的前半段查找,如不是,則找到的k即爲第一個k
int GetFirstK(int* data,int length,int k,int start,int end)
{
if(start>end)
return -1;
int middleIndex=(start+end)/2;
int middleData=data[middleIndex];
if(middleData==k)
{
if((middleIndex>0 && data[middleIndex-1]!=k) || middleIndex==0)
return middleIndex;
else
end=middleIndex-1;
}
else if(middleData>k)
end=middleIndex-1;
else
start=middleIndex+1;
return GetFirstK(data,length,k,start,end);
}
2、找到最後一個k,與找到第一個k類似,需要判斷找到k的下一個數字是否爲k
int GetLastK(int* data,int length,int k,int start,int end)
{
if(start>end)
return -1;
int middleIndex=(start+end)/2;
int middleData=data[middleIndex];
if(middleData==k)
{
if((middleIndex<length-1 && data[middleIndex+1]!=k) || middleIndex==length-1)
return middleIndex;
else
start=middleIndex+1;
}
else if(middleData<k)
start=middleIndex+1;
else
end=middleIndex-1;
return GetLastK(data,length,k,start,end);
}
3、計算k出現的次數
int GetNumberOfK(int* data,int length,int k)
{
int number=0;
if(data!=NULL && length>0)
{
int first=GetFirstK(data,length,k,0,length-1);
int last=GetLastK(data,length,k,0,length-1);
if(first>-1 && last>-1)
number=last-first+1;
}
return number;
}
GetFirstK與GetLastK都是用二分查找法,因此時間複雜度都爲O(logn)。