1.题目描述
小明拿到一个数列a1,a2,…an,小明想知道存在多少个区间[l,r]同时满足下列两个条件:
- r - l + 1 = k;
- 在al,al+1,…ar中存在一个数至少出现t次
输出满足条件的区间个数。
输入:
输入一行三个整数 n,k,t(1<=n,k,t<=10^5).
第二行n个整数,a1,a2,…an(1<=ai<=10^5).
样例输入:
5 3 2
3 1 1 1 2
样例输出:
3
Hint
区间[1,3]中1出现了2次,区间[2,4]中1出现了3次,区间[3,5]中1出现了2次,使用一共有3个区间满足条件
2.分析
其实就是找一个给定大小区间中某元素出现次数>=t,这个查找得方法有很多
1.暴力解法,双重循环
2.可以先区间元素排序,之后使用两个指针,一次遍历就可以找到结果
3.还可以使用哈希表,使用STL中的map,分别统计每个数字出现的次数,之后找出最多的数就可以了,只需要两次遍历。
3.代码:
方法一:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n,k,t;
cin>>n>>k>>t;
vector<int> number(n,0);
for(int i=0;i<n;++i)
{
int num;
cin>>num;
number[i]=num;
}
int count=0;
for(int i=0;i<n-k+1;++i)
{
vector<int> qujian(number.begin()+i,number.begin()+i+k);
int max= 0;
for(int l=0;l<k;++l)
{
int num = qujian[l];
int times = 0;
for(int m=0;m<k;++m)
{
if(num == qujian[m])
++times;
}
if(max<times)
max = times;
}
if(max>=t)
++count;
cout<<count<<endl;
}
cout<<count<<endl;
return 0;
}
方法二:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int getNumberOfK(vector<int>& number)
{
//vector<int> number{1,2,3,3,3,4,4,4,4,4};
int size = number.size();
int left = 0,right = 0;
int max = 0;
while(left <size &&right <size)
{
int num = number[left];
while(right < size && number[right] == num)++right;
if(right - left>max)
max = right - left;
left = right;
}
return max;
}
int main()
{
int n,k,t;
cin>>n>>k>>t;
vector<int> number(n,0);
for(int i=0;i<n;++i)
{
int num;
cin>>num;
number[i]=num;
}
int count=0;
for(int i=0;i<n-k+1;++i)
{
vector<int> qujian(number.begin()+i,number.begin()+i+k);
sort(qujian.begin(),qujian.end());
int max= getNumberOfK(qujian);
if(max>=t)
++count;
cout<<count<<endl;
}
cout<<count<<endl;
return 0;
}
方法三:
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
int findMax(vector<int>& num)
{
map<int,int> times;
for(auto& value:num)
{
++times[value];
}
int max=0;
for(auto& time:times)
{
if(max<time.second)
max = time.second;
}
return max;
}
int main()
{
int n,k,t;
cin>>n>>k>>t;
vector<int> number(n,0);
for(int i=0;i<n;++i)
{
int num;
cin>>num;
number[i]=num;
}
int count=0;
for(int i=0;i<n-k+1;++i)
{
vector<int> num(number.begin()+i,number.begin()+i+k);
if(findMax(num)>=t)
++count;
cout<<count<<endl;
}
cout<<count<<endl;
return 0;
}
其中方法一比较容易想到,只是时间复杂度O(n^2),复杂度比较大。
方法二比较麻烦,需要两个指针,一个指向相同元素的第一个数,另外一个指向相同元素的最后一个数的后面一个位置,通过比较两个指针距离可以得到次数。
方法三如果熟悉map也比较容易,时间复杂度是O(n),实际是2n,使用了一个辅助空间。