数字在排序数组种出现的次数
先修知识点
- 范围for循环:for(元素类型 元素对象:容器对象){ 循环体; } 。用元素对象依次结合容器对象中的每一个元素,每结合一个元素,执行依次循环体,直至容器内的所有元素都被结合完为止。因此可以直接使用元素对象来进行比较判断
- equal_range函数:返回两个数first、second。first为value可插入的第一个位置,second则是在不破坏次序的前提下,value可插入的最后一个位置。equal_range(data.begin(),data.end(),k);使用时要注意是equal_range(迭代器开始,迭代器最后,比较值)
sort(begin, end, cmp)
,其中begin
为指向待sort()
的数组的第一个元素的指针,end
为指向待sort()
的数组的最后一个元素的下一个位置
的指针,cmp
参数为排序准则,如果没有的话,默认以非降序排序。int cmp(int x, int y) { return x > y; } sort(a, a + 2, cmp)。sort(a ,a + len, greater<int>()); //内置类型的由大到小排序。sort(a, a + len, less<int>()); //内置类型的由小到大排序。- lower_bound( )和upper_bound( )函数:lower_bound( )是从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。upper_bound( )从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。lower_bound(begin,end,num)、upper_bound(begin,end,num)
- lower_bound( begin,end,num,greater<type>() )和upper_bound( begin,end,num,greater<type>() )是重载函数,分别是在从大到小的数组中查找一个小于等于和第一个小于的地址。
题目描述
统计一个数字在排序数组中出现的次数。
解题思路
最简单的思路:循环size次,与该数字比较,相同+1。 使用范围for循环:利用元素对象a来对比
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k)
{
int i=0;
for(auto a:data)
{
if(a==k)
i++;
}
return i;
}
};
使用equal_range函数是排序数组中查找与比较值相等的数的范围。也可以用lower_bound()以及upper_bound()来确定范围。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k)
{
int a=0;
/*
auto r=equal_range(data.begin(),data.end(),k);
return a=r.second-r.first;
*/
auto l=lower_bound(data.begin(),data.end(),k);
auto r=upper_bound(data.begin(),data.end(),k);
return a=r-l;
}
};
学习了一下二分法,使用迭代器(l=data.begin,r=data.end,m=l+(r-l)/2) [注:用(l+r)/2可能会超出内存] 以及循环(while(r>=l))来建立二分查找,找到该数值所在位置。 找到之后,通过在其左右区间内循环,计算其出现次数。
特别的要注意:因为循环条件是r>=l,所以一定要先判断data是否为空,否则while一直死循环下去。
class Solution {
public:
int GetNumberOfK(vector<int> data ,int k)
{
int t;
if(!data.size()) return 0;
auto l=data.begin(),r=data.end()-1;
auto m=l+(r-l)/2;
while(r>=l)
{
if(*m==k) break;
if(*m>k) r=m-1;
if(*m<k) l=m+1;
m=l+(r-l)/2;
}
for(auto i=m;i>=l;i--)
{
if(*i==k)
t++;
else
break;
}
for(auto i=m+1;i<=r;i++)
{
if(*i==k)
t++;
else
break;
}
return t;
}
};
特别注意:两个for循环如果都用的是i=m,会多算一次m=k,此时不能在最后return t-1,因为如果0的话会变成-1.因此在程序中第二个for循环使用i=m+1。
用到的二分法就是:(用例找一个数的位置)
class Solution{
public:
int search(vector<int>& nums,int target)
{
int a;
if(!nums.size()) return -1;
auto l=nums.begin(),r=nums.end();
auto m=l+(r-l)/2;
while(r>=l)
{
if(*m==target) return a=m-nums.begin();
if(*m>target) r=m-1;
if(*m<target) l=m+1;
m=l+(r-l)/2;
}
return -1;
}
};
二分法实现最重要的是 区间的重新选择划分,当左区间时用:r=m-1;右区间时用:r=m+1。否则就会超时