30. 小浣熊干脆面

description

Eureka灰常喜欢吃小浣熊干脆面(五香牛肉味,烤肉味,奇奇怪怪味,意大利红烩味,照烧猪排味,香辣蟹味,海苔味,麻辣香锅味,巧克力味,草莓味,玉米味,炸鸡味,奥尔良烤鸡翅味)。以上只是为了馋一下你 ^_^

现在Eureka厌倦了吃干脆面,所以他打算收集齐所有种类的干脆面送给NONO~,但是新一的自动售货机只能买连续的一些干脆面,你能告诉他最少买多少包么?

输入

第一行两个整数n(1 <= n <= 1000000),表示售货机有连续的n袋干脆面, m(1 <= m <= 2000), 表示一共有m种干脆面

第二行有n个整数分别为a1,a2,a2...,an(1 <= ai <= 2000),表示第i袋干脆面是第ai种的


输出

一个整数ans,表示最少购买多少袋(也就是说最短的区间包含1到m所有类型的干脆面,当然Eureka可以等待别人买完前面的一部分再开始买)

样例中Eureka会选择购买5 3 1 3 2 4这一段共6袋

 测试输入 期待的输出 时间限制 内存限制 额外进程
测试用例 2以文本方式显示
  1. 12 5↵
  2. 2 5 3 1 3 2 4 1 1 5 4 3↵
以文本方式显示
  1. 6↵
1秒64M0

code

  1. 建立一个数组a[n] 保存售货机里面所有的干脆面

  2. 建立数组b[m]保存当前取的连续串中每一种干脆面的数量,即b[i]的值就是第i种面的数量,记得初始化为0

  3. 先取一段连续干脆面串,要包含m种干脆面,利用两个指针,头指针指向头部,尾指针指向结尾在这里插入图片描述

  4. 针对取的连续串如果头部的干脆面在中间也有(体现为b[a[head]]>1),那么去掉,体现为 头指针+1,向后移动一位在这里插入图片描述

  5. 现在尾指针-头指针得到一个临时的长度tmplength

  6. 然后从刚才取到的位置开始一直遍历到最后,每次往连续串里面添加一袋面都要重复第4步的操作,进行检查

  7. 重复第5步,得到另一个临时长度tmplength

  8. 在循环中用最小长度minlength和每一个临时长度tmplength作比较决定是否更新,最后取到最小的length来输出

代码:

#include <stdio.h>
#include <string.h>

#define N1 1000010
#define N2 2005

int a[N1];  //售货机里有的干脆面

int main()
{
    int n, m;

    int b[N2];  // b[i]:在暂时取的连续干脆面中,m种干脆面中第i种的数量
    int head, tail, len, minlen;
    int count = 0;  //计数器
    int i;

    // freopen("file.txt", "r", stdin);
    scanf("%d %d", &n, &m);
    for(i = 0; i < n; i++)
        scanf("%d", &a[i]);

    //初始化
    head = 0;
    tail = 0;
    len = 0;
    minlen = N1;
    memset(b, 0, sizeof(b));
    //先取一段包含m种干脆面的连续干脆面
    for(i = 0; count < m && i < n; i++) {
        //现在要把a[i]取进来
        if(b[a[i]] == 0) {  //避免重复计算数量,只有第一次取这一种计数器才增加
            count++;
        }
        b[a[i]]++;  //第a[i]种干脆面数量+1;
        tail++;  //尾指针向后移动一位
    }

    //先计算得到一个最小长度
    //先去掉头部重复的
    while(b[a[head]] > 1) {
        b[a[head]]--;
        head++;
    }
    len = tail - head;
    if(minlen > len)
        minlen = len;

    //然后依次向后遍历,每加进来一袋面都要判断一下
    for(i = tail; i < n; i++) {
        b[a[i]]++;
        tail++;
        while(b[a[head]] > 1) {  //如果添加进来的使得前面有可以不买的,删掉
            b[a[head]]--;
            head++;
        }
        //每次去掉头部的重复干脆面之后要重新更新一下长度
        len = tail - head;
        if(minlen > len)
            minlen = len;
    }
    printf("%d\n", minlen);

    return 0;
}

// 12 5
// 2 5 3 1 3 2 4 1 1 5 4 3

summary

  1. 刚开始我把数组a[N]声明在main函数里面,然后vscode就报错了,可以看看这个https://blog.csdn.net/qq_41680771/article/details/121711998
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值