数字在排序数组中出现的次数

题目:

统计一个数字在排序数组中出现的次数。

方法一:暴力匹配

时间复杂度:O(n)

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) 
    {
        int count=0;
        for(int i=0;i<data.size();i++)
        {
            if(data[i]==k)
                count++;
            else if(data[i]>k)
                break;
        }
        return count;
    }
};

方法二:二分法

由于是排序数组,可以使用二分查找,找到第一个K和最后一个K 二者位置相减

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) 
    {
        int len=data.size();
        int FirstK=GetFirstK(data,k,0,len-1);
        int LastK=GetLastK(data,k,0,len-1);
        if(FirstK!=-1&&LastK!=-1)
            return LastK-FirstK+1;
        return 0;
    }
    private:
    int GetFirstK(vector<int>data,int k,int begin,int end)
    {
        if(begin>end)
            return -1;
        int mid=(begin+end)/2;
        if(data[mid]>k)
            return GetFirstK(data, k, begin, mid-1);
        else if(data[mid]<k)
            return GetFirstK(data, k, mid+1, end);
        else if(mid-1>=0&&data[mid-1]==k)
            return GetFirstK(data, k, begin, mid-1);
        else
            return mid;
    }

    int GetLastK(vector<int>data,int k,int begin,int end)
    {
        if(begin>end)
            return -1;
        int mid=(begin+end)/2;
        if(data[mid]>k)
            return GetLastK(data, k, begin, mid-1);
        else if(data[mid]<k)
            return GetLastK(data, k, mid+1, end);
        else if(mid+1<=end&&data[mid+1]==k)
            return GetLastK(data, k, mid+1, end);
        else
            return mid;
    }
};

下面用循环来代替递归

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) 
    {
        int len=data.size();
        int FirstK=GetFirstK(data,k,0,len-1);
        int LastK=GetLastK(data,k,0,len-1);
        if(FirstK!=-1&&LastK!=-1)
            return LastK-FirstK+1;
        return 0;
    }
    private:
    int GetFirstK(vector<int>data,int k,int begin,int end)
    {
        int mid=(begin+end)/2;
        while(begin<=end)
        {
            if(data[mid]>k)
                end=mid-1;
            else if(data[mid]<k)
                begin=mid+1;
            else if(mid-1>=0&&data[mid-1]==k)
                end=mid-1;
            else
                return mid;
            mid=(begin+end)/2;                 //不要忘了重置mid
        }
        return -1;
    }

    int GetLastK(vector<int>data,int k,int begin,int end)
    {
        int mid=(begin+end)/2;
        while(begin<=end)
        {
            if(data[mid]>k)
                end=mid-1;
            else if(data[mid]<k)
                begin=mid+1;
            else if(mid+1<=end&&data[mid+1]==k)
                begin=mid+1;
            else
                return mid;
            mid=(begin+end)/2;
        }
        return -1;
    }
};

方法三:

同样采用二分法,不过二分法找出的是任意一个出现k的位置,从该位置开始,前后遍历,递加计数器,得到k出现的个数

class Solution {
public:
    int PositionOfK(vector<int>data,int k,int begin,int end)
    {
        int mid=(begin+end)/2;
        while(begin<=end)
        {
            if(data[mid]==k)
                return mid;
            else if(data[mid]>k)
                end=mid-1;
            else
                begin=mid+1;
            mid=(begin+end)/2;
        }
        return -1;
    }

    int GetNumberOfK(vector<int> data ,int k) 
    {
        int len=data.size();
        int position=PositionOfK(data,k,0,len-1);
        if(position==-1)
            return 0;
        int count=0;
        int i=position;
        while(data[i]==k&&i<=len-1)
        {
            count++;
            i++;
        }
        i=position-1;
        while(data[i]==k&&i>=0)
        {
            count++;
            i--;
        }
        return count;
    }
};

方法四:

因为data中都是整数,所以可以稍微变一下,不是搜索k的两个位置,而是搜索k-0.5和k+0.5这两个数应该插入的位置,然后相减即可。

class Solution {
public:
    int MyInsert(vector<int>data,double num)
    {
        int len=data.size();
        int begin=0,end=len-1;
        while(begin<=end)
        {
            int mid=(begin+end)/2;
            if(data[mid]>num)
                end=mid-1;
            if(data[mid]<num)
                begin=mid+1;
        }
        return end;
    }

    int GetNumberOfK(vector<int> data ,int k) 
    {
       return MyInsert(data,k+0.5)-MyInsert(data,k-0.5);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值