美团点评2019年校招编程题——区间统计

1.题目描述

小明拿到一个数列a1,a2,…an,小明想知道存在多少个区间[l,r]同时满足下列两个条件:

  1. r - l + 1 = k;
  2. 在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,使用了一个辅助空间。

猜你喜欢

转载自blog.csdn.net/zqw_yaomin/article/details/82495301