剑指offer:数字在排序数组中出现的次数

1.题目描述:

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

2.解题思路:

 在一个已经排好序的数组中找一个数最先想到的应该是使用二分法查找,由于需要找的数是重复出现多次的,此时的二分查找需要一些技巧。注意到给出的数据类型是vector型,要找的数是k,可以通过查找k-0.5来确定比k-0.5大一点且最接近k-0.5的位置(此时如果k存在于数组中,该位置就是第一个k值得位置),再通过查找k+0.5,找到比k+0.5大一点且最接近k+0.5的位置(此时的位置是数组中距离k最近且比k大一点的数的位置)。

3.代码:

  1 class Solution {
  2 public:
  3     int GetNumberOfK(vector<int> data ,int k) {
  4         if(data.size() == 0)
  5         {
  6             return 0;
  7         }
  8         int left = sortnum(data, k-0.5);
  9         int right = sortnum(data, k+0.5);
 10         return right -left;
 11     }
 12 private:
 13     int sortnum(vector<int> data, float k)
 14     {
 15         int size = data.size();
 16         int left = 0;
 17         int right = size - 1;
 18         int mid = right/2;
 19         for(int i = 0; i<size; i++)
 20         {
 21             if(data[mid] > k)
 22             {
 23                 right = mid;
 24                 mid = left + (right - left)/2;
 25             }
 26             if(data[mid] < k)
 27             {
 28                 left = mid;
 29                 mid = left + (right - left)/2;
 30             }
 31             if(right - left == 1)
 32                 return right;
 33         }
 34         return 0;
 35     }
 36 };

 这种方法无法通过所有的测试用例,比如说:[3,3,3,3,4,5],3。32行的return right代码中在该测试用例下返回的是第二个3的位置,这是错误的,应该返回第一个3的位置。如果将其修改为return left,则碰到[3,4,5,5,5],5这种测试用例时又会返回倒数第二个5的位置。应该返回倒数第一个。
 对上述问题进行分析,我们应该要找的是k-0.5与k+0.5在排序数组中应该插入的位置,因为这两个浮点数是我们构造出来的,在原数组中并不存在,所以二分查找的最终结果总是[a1,a2]。当a1不等于a2时,k-0.5位于a1与a2之间,就二分查找的左边情况来看,在data[mid]

class Solution {
public:
    int GetNumberOfK(vector<int> data ,int k) {
        if(data.size() == 0)
        {
            return 0;
        }
        int left = sortnum(data, k-0.5);
        int right = sortnum(data, k+0.5);
        return right - left; 
    }
private:
    int sortnum(vector<int> data, float k)
    {
        int size = data.size();
        int left = 0;
        int right = size - 1;
        int mid = right/2;
        while(left<=right)
        {
            if(data[mid] > k)
            {
                right = mid-1;
                mid = left + (right - left)/2;
            }
            if(data[mid] < k)
            {
                left = mid+1;
                mid = left + (right - left)/2;
            }
        }
        return left;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值