题目描述
统计一个数字在排序数组中出现的次数。
思路
- 首先需要注意的问题,这个数组是递增还是递减,
不过测试样例都是递增的… - 排序的数组我们应该要想到二分查找,只不过如果我们通过二分查找找到第一个k不能保证这个k是第一个或者最后一个,这样你还是通过这个k的位置从前从后进行顺序查找,时间复杂度退化为 O ( n ) O(n) O(n),跟普通的顺序查找就没什么不同的
- 那么,我们可以通过二分查找找到第一个K和最后一个k的下标,然后两者之差就是出现的次数
- 如果找到第一个和最后一个k,也是可以通过二分查找进行,关键在于当我们找到k时只需要判断他是不是最后一个k或者第一个k即可,如果不是,则区间进行更新。时间复杂度为 O ( log n ) O(\log n) O(logn)。
AC代码
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int count = 0;
if (data.size() > 0)
{
int begin = first_index(data,k);
int last = last_index(data,k);
if (begin > -1 && last > -1)
count = last-begin+1;
}
return count;
}
//前提是这个数组是递增的
int first_index(vector<int> data,int k)
{//找到第一个k
int low = 0;
int high = data.size()-1;
while (low <= high)
{
int mid = low + (high-low)/2;//防止溢出
if (data[mid] == k) //判断此时这个k是不是第一个k
{
if(data[mid-1] != k && mid > 0 || mid == 0)
return mid;
else
high = mid-1;//不是第一个k,说明第一个k在mid前面
}
else if (data[mid] > k)
high = mid -1;
else
low = mid + 1;
}
return -1; //没有找到
}
int last_index(vector<int>data, int k)
{//找到最后一个K
int low = 0;
int high = data.size()-1;
while (low <= high)
{
int mid = low + (high-low)/2;
if (data[mid] == k) //判断是不是最后一个k
{ //判断是否越界
if (data[mid+1] != k && mid+1 <= data.size()-1 || mid == data.size()-1)
return mid;
else
low = mid + 1;
}
else if (data[mid] > k)
high = mid-1;
else
low = mid + 1;
}
return -1;
}
};
总结
- 对于排序的数组的查找,应该想到使用二分查找
- 二分查找需要注意的细节就是防止溢出:int mid = low + (high-low)/2;