day40:67. 数字在排序数组中出现的次数(二分查找)

54 篇文章 2 订阅
17 篇文章 0 订阅

问题描述:
统计一个数字在排序数组中出现的次数。
例如输入排序数组[1, 2, 3, 3, 3, 3, 4, 5]和数字3,由于3在这个数组中出现了4次,因此输出4。
样例

  • 输入:[1, 2, 3, 3, 3, 3, 4, 5] , 3
  • 输出:4

使用二分搜索,只不过是经典案例的改编,经典案例是寻找一个数字,该数字并不是重复的,而本题目是寻找一个数字出现的次数,该数字会出现多次,折半查找的思路是:
1)设置初始查找区间:low=0,high=n-1
2)测试查找区间是否存在,如果不存在,则查找失败,否则
3)取中间点mid=(low+high)/2 比较k 和 rmid,有三种情况:

  • k<rmid high=mid-1,查找在左半区进行,转步骤2
  • k>rmid low=mid+1,查找在右半区进行,转步骤2
  • k=rmid,则查找成功,返回记录在表中的位置

只不过在该题中不需要k=rmid这一步,只需要找到左右边界,然后相减即可得到该数字出现的次数。

有两种二分模板,第一种二分模板是寻找左边第一个数,第二个模板是寻找最后一个数字。要想找左边第一个数,需要找到左边与右边一个划分的性质,即nums[mid] < k ,此时是左边的拐点,要求解的值在右边区间内,因此l=mid+1;要想找最后一个数字,那么划分右边与左边的性质是nums[i] <=k ,这样说明mid在要寻找的数字区间内,需要将左区间向右移动,即l = mid. 最后注意数组个数为0的情况,求解到要找数字的左右边界,二者相减就可以得到。
在这里插入图片描述

class Solution {
public:
    int getNumberOfK(vector<int>& nums , int k) {
        if(nums.empty()) return 0;
        
        int l=0,r=nums.size()-1;
        while(l<r)
        {
            int mid=l+r>>1;
            if(nums[mid]<k) l=mid+1;
            else r=mid;
        }
        if(nums[l]!=k) return 0;
        
        int left=l;
        
        l=0,r=nums.size()-1;
        while(l<r)
        {
            int mid= l+r+1>>1;//注意加一防止陷入死循环
            if(nums[mid]<=k) l=mid;
            else r=mid-1;
        }
        
        return r-left+1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值