题目描述:
统计一个数字在排序数组中出现的次数。
比如排序数组为{1,2,3,3,3,4,5},那么数字3出现的次数就是3。
解题思路:
既然是已经排序好的数组,那么第一个想到的就是二分查找法。
做法就是使用二分法找到数字在数组中出现的第一个位置,再利用二分法找到数字在数组中出现的第二个位置。时间复杂度为o(logn logn),最终的时间复杂度为o(logn)。
举个例子,找到数字k在数组data中出现的次数。
数组data中,数字k出现的第一个位置:
我们对数组data进行二分,如果数组中间的数字小于k,说明k应该出现在中间位置的右边;如果数组中间的数字大于k,说明k应该出现在中间位置的左边;如果数组中间的数字等于k,并且中间位置的前一个数字不等于k,说明这个中间数字就是数字k出现的第一个位置。
同理,数字k出现的最后一个位置,也是这样找的。但是判断少有不同。我们使用两个函数分别获得他们。
代码实现(c )
class solution {
public:
int getnumberofk(vector data ,int k) {
int length = data.size();
if(length == 0){
return 0;
}
int first = getfirstk(data, k, 0, length - 1);
int last = getlastk(data, k, 0, length - 1);
if(first != -1 && last != -1){
return last - first 1;
}
return 0;
}
private:
// 迭代实现找到第一个k
int getfirstk(vector data, int k, int begin, int end){
if(begin > end){
return -1;
}
int middleindex = (begin end) >> 1;
int middledata = data[middleindex];
if(middledata == k){
if((middleindex > 0 && data[middleindex - 1] != k) || middleindex == 0){
return middleindex;
}
else{
end = middleindex - 1;
}
}
else if (middledata > k){
end = middleindex - 1;
}
else{
begin = middleindex 1;
}
return getfirstk(data, k, begin, end);
}
// 循环实现找到最后一个k
int getlastk(vector data, int k, int begin, int end){
int length = data.size();
int middleindex = (begin end) >> 1;
int middledata = data[middleindex];
while(begin <= end){
if(middledata == k){
if((middleindex < length - 1 && data[middleindex 1] != k) || middleindex == length - 1){
return middleindex;
}
else{
begin = middleindex 1;
}
}
else if(middledata > k){
end = middleindex - 1;
}
else{
begin = middleindex 1;
}
middleindex = (begin end) >> 1;
middledata = data[middleindex];
}
return -1;
}
};