一、题目
题目链接:力扣
统计一个数字在排序数组中出现的次数。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109
二、题解
1、思路
🍊 暴力查找
数大了肯定没二分法快哦。
🍊 二分查找
直观的思路肯定是从前往后遍历一遍。用两个变量记录第一次和最后一次遇见 target 的下标,但这个方法的时间复杂度为 O(n),没有利用到数组升序排列的条件。
大体思路:
很经典的题,两次二分查找x,一次找到x元素最左边位置,一次找到x元素最右边的位置,最终返回的是右边的位置减左边的位置 + 1。当数组大小为零时候特殊处理,返回0。
自定义二分查找函数的算法流程:
2、代码实现
🍊 暴力查找
class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.size() == 0)return 0;
int res = 0;
for(auto& number : nums)
{
if(number == target)res++;
}
return res;
}
};
🍊 二分查找
使用C++ STL库函数: lower_bound、 upper_bound。
【C++】从没见过这么详细的lower_bound的讲解_am brother的博客-CSDN博客
- lower_bound:返回一个非递减序列[first, last)中的第一个大于等于值val的位置;
- upper_bound:返回一个非递减序列[first, last)中第一个大于val的位置。
class Solution {
public:
int search(vector<int>& nums, int target) {
// 查找非递减序列nums中第一个大于target - 1的位置
int left = upper_bound(nums.begin(), nums.end(), target - 1) - nums.begin();
// 查找非递减序列nums中第一个大于target的位置
int right = upper_bound(nums.begin(), nums.end(), target) - nums.begin();
return right - left;
}
};
看不懂二分法?看这里,一文搞懂二分查找!二分法(数组中无重复数字、包含重复数字两种情况)_Kashine的博客-CSDN博客
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
if(n == 0)return 0;
int left = binary_research(nums, 0, n-1, target);
int right = binary_research2(nums, 0, n - 1, target);
if(left == -1)return 0;
if(right == -1)return n - left;
else return right - left;
return -1;
}
// 大于等于target的第一个数字下标
int binary_research(vector<int>& nums, int i, int j, int target)
{
if(nums.size() == 0)return 0;
int res = -1;
while(i <= j)
{
int mid = i + (j-i)/2;
if(nums[mid] >= target)
{
j = mid - 1;
res = mid;
}
else
{
i = mid +1;
}
}
return res;
}
// 大于target的第一个数字下标
int binary_research2(vector<int>& nums, int i, int j, int target)
{
if(nums.size() == 0)return 0;
int res = -1;
while(i <= j)
{
int mid = i + (j-i)/2;
if(nums[mid] > target)
{
j = mid - 1;
res = mid;
}
else
{
i = mid +1;
}
}
return res;
}
};
3、复杂度分析
🍊 暴力查找
时间复杂度:O(n);
空间复杂度:O(1)。
🍊 二分查找
时间复杂度:O(logn);(以2为底)
空间复杂度:O(1)。
4、运行结果
🍊 暴力查找
🍊 二分查找
STL函数版本:
自定义函数版本: