2019腾讯实习提前批笔试题-气球游戏(滑动窗口)

小Q在进行射击气球的游戏,如果小Q在连续T枪中打爆了所有颜色的气球,将得到一只QQ公仔作为奖励。(每种颜色的球至少被打爆一只)。

这个游戏中有m种不同颜色的气球,编号1到m。

小Q一共有n发子弹,然后连续开了n枪。

小Q想知道在这n枪中,打爆所有颜色的气球最少用了连续几枪?

输入格式

第一行包含两个整数n和m。

第二行包含n个整数,分别表示每一枪打中的气球的颜色,0表示没打中任何颜色的气球。

输出格式

一个整数表示小Q打爆所有颜色气球用的最少枪数。

如果小Q无法在这n枪打爆所有颜色的气球,则输出-1。

数据范围

1≤n≤1061≤n≤106,
1≤m≤20001≤m≤2000

输入样例:

12 5
2 5 3 1 3 2 4 1 0 5 4 3

输出样例:

6

样例解释

有五种颜色的气球,编号1到5。

游客从第二枪开始直到第七枪,这连续六枪打爆了5 3 1 3 2 4这几种颜色的气球,包含了从1到5的所有颜色,所以最少枪数为6。

思路:用两个指针,每次后指针往后移,移到符合颜色数时,前指针看看能不能在符合颜色数的前提下往后移一点。最后每次比较一下长度即可。

#include 
#include 
using namespace std;
#define N 1010000
#define M 2020

int n, m, a[N], v[M];

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    int color = 0, res = -1;
    for(int i = 1, j = 0; i <= n; i++)
    {
        if(a[i] && !v[a[i]]) color++;
        v[a[i]]++;
        if(color == m)
        {
            while(j <= n && (!a[j] || v[a[j]] > 1))
            {
                v[a[j]]--;
                j++;
            }
            if(res == -1 || res > i-j+1)
                res = i-j+1;
        }
    }
    cout << res << endl;
    return 0;
}

/* //比较臃肿的写法
int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> a[i];
    int i = 1, j = 0, cnt = 0, res = -1;
    while(i <= n && j <= n)
    {
        while(j <= n && cnt != m)
        {
            j++;
            if(a[j] != 0 && v[a[j]] == 0) cnt++;
            v[a[j]]++;
        }
        if(cnt != m)
        {
            cout << -1 << endl;
            return 0;
        }
        while(i <= n)
        {
            if(a[i] == 0 || v[a[i]] > 1)
            {
                v[a[i]]--;
                i++;
            }
            else break;
        }
        if(res == -1 || res > j-i+1)
            res = j-i+1;
        j++;
        v[a[j]]++;
    }
    cout << res << endl;
    return 0;
}
*/

 

你可能感兴趣的:(心得算法)