题目描述
统计一个数字在排序数组中出现的次数。
考察点:二分查找的应用;知识迁移能力。
思路:可以直接想到时间复杂度为O(n)的从前到后的遍历方法。
这里采用二分查找法,找到特定出现的k,如果中间的数字比k 大,那么第一次出现的k 只能出现在前半段,如果中间的数字比k小,那么第一次出现k的位置只能在后半段,如果相等的话,如果这个数组前面一个不是k,那么就可以返回下标位置了,如果是k,说明不是第一个出现的k,那么需要接着向前找。同理,找最后一次出现k的位置也是这样二分查找并且递归。
class Solution {
public:
int getFirstK(vector<int> data, int k, int begin, int end)
{
if (begin > end)
return -1;
int midIndex = (begin + end) / 2;
int midData = data[midIndex];//初始中值和下标
if (midData == k)//三种情况的判断
{
if ((midIndex > 0 && data[midIndex - 1] != k) || midIndex == 0)//符合第一个k的条件
{
return midIndex;
}
else
end = midIndex - 1;
}
else if (midData > k)
{
end = midIndex - 1;
}
else
begin = midIndex + 1;
return getFirstK(data, k, begin, end);//继续递归查找
}
int getLastK(vector<int> data, int k, int begin, int end)
{
if (begin > end)
return -1;
int midIndex = (begin + end) / 2;
int midData = data[midIndex];
if (midData == k)
{
if ((midIndex != end && data[midIndex + 1] != k) || midIndex == end)
return midIndex;
else
begin = midIndex + 1;
}
else if (midData > k)
{
end = midIndex - 1;
}
else
begin = midIndex + 1;
return getLastK(data, k, begin, end);
}
int GetNumberOfK(vector<int> data, int k)
{
int number = 0;
int length = data.size();
if (!data.empty())
{
int first = getFirstK(data, k,0,length-1);
int last = getLastK(data, k,0, length - 1);
if (first > -1 && last > -1)//都可以找到其实,一个符合两个都符合
number= last - first + 1;
}
return number;
}
};