题目描述
统计一个数字在升序数组中出现的次数。
示例
输入:
{1, 2, 3, 3, 3, 3, 4, 5}, 3
输出:
4
解题思路及代码
方法一:暴力方法
即遍历一遍数组,统计该数字出现的次数。(没用到该数组是一个升序数组这一性质)
代码如下:
class Solution {
public:
int GetNumberOfK(vector<int> nums ,int target) {
int ret = 0;
for (int val : nums) {
if (val == target)
++ret;
}
return ret;
}
};
时间复杂度:O(N)
空间复杂度:O(1)
方法二:二分查找
思路:我们通过二分查找找到该数字在数组中的上界和下界,然后上界减去下界即是出现的次数。
下界定义为:如果存在目标值,则指向第一个目标值,否则,如果不存在, 则指向大于目标值的第一个值。
上界定义为:不管目标值存在与否,都指向大于目标值的第一个值。
如图:
代码如下:
class Solution {
public:
int GetNumberOfK(vector<int> nums ,int target) {
int lbound = 0, rbound = 0;
// 寻找下界
int l = 0, r = nums.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] < target) { // 注意是小于号
l = mid + 1;
}
else {
r = mid;
}
}
lbound = l;
// 寻找上界
l = 0, r = nums.size();
while (l < r) {
int mid = l + (r - l) / 2;
if (nums[mid] <= target) { // 注意是小于等于号
l = mid + 1;
}
else {
r = mid;
}
}
rbound = l;
return rbound - lbound;
}
};
或者直接使用 STL 中的 upper_bound(), lower_bound()
库函数:
class Solution {
public:
int GetNumberOfK(vector<int> nums ,int target) {
return upper_bound(nums.begin(), nums.end(), target) - lower_bound(nums.begin(), nums.end(), target);
}
};
这两个函数定义于头文件<algorithm>
。
upper_bound():返回指向范围[first, last)
中首个 大于value
的元素的迭代器,或若找不到这种元素则返回last
。采用 二分实现,所以调用前必须保证有序。
lower_bound():返回指向范围[first, last)
中首个 不小于(即大于或等于)value
的元素的迭代器,或若找不到这种元素则返回last
。
时间复杂度:O(logN)
空间复杂度:O(1)