数字在排序数组中出现的次数
题目描述
统计一个数字在排序数组中出现的次数
思路
- 一种方法就是直接扫描数组中的每个数字,进行统计这个数字在数组中出现的次数,但是这个算法时间复杂度为O(n)级别的,不是太好.
- 另外一种方法是利用二分查找的想法,假定要查找的数字为k,首先找到数组中的第一个k在数组中的位置index1,然后找到最后一个k在数组中的位置index2,该数字k出现的次数就为index2-index1+1,这样时间复杂度就是O(logn),效率会大大提升。
具体思路
- 对于任何找到K第一次出现的位置index1,可以对数组进行二分,如果中间的数字大于k,则index1的位置应该在中间位置的左边;如果小于k,index1的位置应在中间的右边;如果等于k,而且中间数字的前一位不是k,则这个位置就是index1。
- 对于最后一次出现的位置index2,对于中间数字大于和小于k的情况,处理方式跟找index1的方式一样,在第三种情况,即在中间数字等于k,而且中间数字的后一位不是k时,这个位置时index2。
具体代码
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int len=data.size();
if(len==0)return 0;
int number=0;
int first=getFirst(data,k,0,len-1);
int last=getLast(data,k,0,len-1);
//出现次数index2-index1+1
if(first>-1&&last>-1){
number=last-first+1;
}
return number;
}
//找第一个k,即index1
int getFirst(vector<int>&data,int k,int begin,int end){
if(begin>end)return -1;
int middleIndex=(end+begin)/2;
int middleData=data[middleIndex];
if(middleData==k){
//前一个数字不为k
if(data[middleIndex-1]!=k||middleIndex==0)return middleIndex;
else end=middleIndex-1;
}
else if(middleData>k)end=middleIndex-1;
else begin=middleIndex+1;
return getFirst(data,k,begin,end);
}
//找最后一个k,即index2
int getLast(vector<int>&data,int k,int begin,int end){
if(begin>end)return -1;
int middleIndex=(end+begin)/2;
int middleData=data[middleIndex];
if(middleData==k){
//后一个数字为k
if(data[middleIndex+1]!=k||middleIndex==data.size()-1)return middleIndex;
else begin=middleIndex+1;
}
else if(middleData>k)end=middleIndex-1;
else begin=middleIndex+1;
return getLast(data,k,begin,end);
}
};