剑指offer-数字在排序数组中出现的次数(c++ 多种方法)

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

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

题解:
1)暴力穷举法:
一一比较,输出次数
2)二分法——相同数字遍历法:
通过二分法,找到目标数字在排序数组中的一个位置。通过该位置用两个指针对其进行前后遍历,当指针指向的数字不为目标数字时停止。
代码如下:

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        if(data.size()==0) return 0;
        int res=0;
        int l=0;
        int r=data.size()-1;
        if(data[l]==k&&data[r]==k) return r+1;
        int mid=(l+r)/2;
        while(l<=r){
            if(data[mid]==k)
                break;
            if(data[mid]<k)
                l=mid+1;
            if(data[mid]>k)
                r=mid-1;
            mid=(l+r)/2;
        }
        int mid1=mid;
        while(data[mid1]==k&&mid1>=l){
            mid1--;res++;
        }
        while(data[mid+1]==k&&mid<=r){
            mid++;res++;
        }
        return res;
   }
}

2)二分法——查找前后首次和最后一次出现的位置:
通过二分法,找到目标数字在数组中的一个位置,然后根据前后指针,将数组分为两个子数组,在左数组中查找首次出现目标数字的位置;在右数组中查找最后一次出现目标数字的位置,二者相减+1.
代码如下:

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        /*if(data.size()==0) return 0;
        int res=0;
        int l=0;
        int r=data.size()-1;
        if(data[l]==k&&data[r]==k) return r+1;
        int mid=(l+r)/2;
        while(l<=r){
            if(data[mid]==k)
                break;
            if(data[mid]<k)
                l=mid+1;
            if(data[mid]>k)
                r=mid-1;
            mid=(l+r)/2;
        }
        int mid1=mid;
        while(data[mid1]==k&&mid1>=l){
            mid1--;res++;
        }
        while(data[mid+1]==k&&mid<=r){
            mid++;res++;
        }
        return res;*/
        if(data.size()==0) return 0;
        int res=0;
        int l=0;
        int r=data.size()-1;
        if(data[l]==k&&data[r]==k) return r+1;//数组全为目标数字
        if(r==l&&data[l]!=k) return 0; //数组大小为1,且不为目标数字
        int mid;
        while(l<=r){
            int mid=(l+r)>>1;
            if(data[mid]==k) break;//首次查找目标数字的一个位置
            if(data[mid]<k) l=mid+1;
            if(data[mid]>k) r=mid-1;
        }
        int r1=r;
        int l1=mid;
        r=mid-1;
        while(l<=r){//查找目标首次出现位置
            if(data[(l+r)/2]<k)
                l=(l+r)/2+1;
            else if((l+r)/2-1>=l && data[(l+r)/2-1]==k){
                r=(l+r)/2-1;
            }
            else 
                break;
        }
        while(l1<=r1){//查找目标最后一次出现的位置
            if(data[(l1+r1)/2]>k){
                r1=(l1+r1)/2-1;
            }
            else if((l1+r1)/2+1<=r1 && data[(l1+r1)/2+1]==k)
                l1=(l1+r1)/2+1;
            else 
                break;
        }
        if((l1+r1)/2==(l+r)/2)//防止数组中不存在目标数字
            return 0;
        res=(l1+r1)/2-(l+r)/2+1;
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值