描述
给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数
数据范围: 0 ≤ n ≤ 1000,0 ≤ k ≤ 100,数组中每个元素的值满足 0 ≤ val ≤ 100
要求:空间复杂度 O(1),时间复杂度 O(logn)
示例1
输入:[1,2,3,3,3,3,4,5],3
返回值:4
示例2
输入:[1,3,4,5],6
返回值:0
方法一:暴力方法
查找数组中某个目标,不管数组是否有序,直接遍历一遍即可。
代码
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int ret = 0;
for (int val : data) {
if (val == k)
++ret;
}
return ret;
}
};
运行时间:5ms
超过3.82% 用C++提交的代码
占用内存:524KB
超过27.56%用C++提交的代码
时间复杂度:O(N)
空间复杂度:O(1)
方法二:二分查找
显然方法一没有把数组有序的条件利用上,也很显然是利用二分查找。因为有序,所以目标值 k 如果有多个,肯定是连在一起。又已知我们可以在有序数组中查找任意一个值,因此我们可以先查找目标范围的下界和上界。
下界定义为:如果存在目标值,则指向第一个目标值,否则,如果不存在, 则指向大于目标值的第一个值。
上界定义为:不管目标值存在与否,都指向大于目标值的第一个值。
如下图所示:
最后的结果就是:right - left
代码
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k) {
int lbound = 0, rbound = 0;
// 寻找上界
int l = 0, r = data.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (data[mid] < k) {
l = mid + 1;
}
else {
r = mid;
}
}
lbound = l;
// 寻找下界
l = 0, r = data.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (data[mid] <= k) {
l = mid + 1;
}
else {
r = mid;
}
}
rbound = l;
return rbound - lbound;
}
};
运行时间:6ms
超过2.29% 用C++提交的代码
占用内存:524KB
超过27.56%用C++提交的代码
时间复杂度:O(logN)
空间复杂度:O(1)