一刷剑指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)。

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