统计一个数字在排序数组中出现的次数。
例如输入排序数组 [1,2,3,3,3,3,4,5] 和数字 3,由于 3 在这个数组中出现了 4 次,因此输出 4。
样例
输入:[1, 2, 3, 3, 3, 3, 4, 5] , 3
输出:4
最近学习了c++中的STL容器和库函数,对于这两者的熟练掌握可以有效提高算法竞赛中用c++编写程序的效率。
现在用两种容器:vector,multiset和库函数lower_bound和upper_bound做一下这道题。
vector:可变长数组。
class Solution {
public:
int getNumberOfK(vector<int>& nums , int k) {
int _count=0;
for(auto x: nums)
if(x==k) _count++;
return _count;
}
};
multiset:有序多重集合,即可包含若干相等元素,其内部实现为红黑树。
class Solution {
public:
int getNumberOfK(vector<int>& nums , int k) {
multiset<int> Set;
for(auto x: nums) Set.insert(x);
return Set.count(k);
}
};
lower_bound:在有序序列中两个迭代器(或指针)指定部分二分查找,返回第一个 大于等于x 的元素的位置的迭代器(或指针)。
upper_bound:用法和lower_bound大致相同,唯一的区别是查找第一个 大于x 的元素。
class Solution {
public:
int getNumberOfK(vector<int>& nums , int k) {
auto left=lower_bound(nums.begin(),nums.end(),k);
auto right=upper_bound(nums.begin(),nums.end(),k);
return right-left;
}
};
当然,这道题还是个典型的整数二分题。
用底层方法实现一下:
class Solution {
public:
int getNumberOfK(vector<int>& nums , int k) {
if(!nums.size()) return 0;
int l=0,r=nums.size()-1;
while(l<r)
{
int mid=l+r>>1;
if(nums[mid]<k) l=mid+1;//答案(左边界元素)在右边部分,由于不等于k则不包含mid,即l不可等于mid
else r=mid;
}
if(nums[l]!=k) return 0;
int left=l;
l=0;
r=nums.size()-1;
while(l<r)
{
int mid=l+r+1>>1;//当更新方式有l=mid时mid应取l+r+1>>1
if(nums[mid]>k) r=mid-1;
else l=mid;
}
int right=r;
return right-left+1;
}
};