一刷劍指offer(38)——數字在排序數組中出現的次數

題目:
統計一個數字在排序數組中出現的次數。例如輸入排序數組{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)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章