不开心的小朋友_200分_B卷_逻辑分析模拟/数据结构

不开心的小朋友

题目描述:

  游乐场里增加了一批摇摇车,非常受小朋友欢迎,但是每辆摇摇车同时只能有一个小朋友使用,如果没有空余的摇摇车需要排队等候,或者直接离开,最后没有玩上的小朋友会非常不开心。
请根据今天小朋友的来去情况,统计不开心的小朋友数量
  1.摇摇车数量为N,范围是: 1 <= N < 10;
  2.每个小朋友都对应一个编码,编码是不重复的数字,今天小朋友的来去情况,可以使用编码表示为:1 1 2 3 2 3。(若小朋友离去之前有空闲的摇摇车,则代表玩耍后离开;不考虑小朋友多次玩的情况)。小朋友数量≤ 100
  3.题目保证所有输入数据无异常且范围满足上述说明

输入输出描述:

输入描述:

  第一行: 摇摇车数量
  第二行: 小朋友来去情况

输出描述:

  返回不开心的小朋友数量

示例1:

输入:
	1
	1 2 1 2
输出:
	0
说明:
	第一行,1个摇摇车
	第二行,1号来 2号来(排队)
	第三行,1号走 2号走(1号走后摇摇车已有空闲,所以玩后离开)

示例2:

输入:
	1
	1 2 2 3 1 3
输出:
	1
说明:
	第一行,1个摇摇车
	第二行,1号来 2号来(排队) 2号走(不开心离开) 3号来(排队) 1号走 3号走(1号走后摇摇车已有空闲,所以玩后离)

示例3:

输入:
	3
	1 2 3 4 5 6 7 3 8 2 1 6 8 7 5 4
输出:
	1
说明:
	第一行,3个摇摇车
	最终只有8号没有坐过车

解题思路:

如下图(先看图,理解最后分析过程)所示,是示例3的过程分析,由此可以得出解决问题的思路如下:
1、使用一个数来记录空闲小车的数量;使用一个Set来记录小朋友出现的历史记录(方便判断小朋友是第一次出现还是第二次,如果是第二次则说明他是要离开了);使用两个结构(Set、List)来记录等待的小朋友,Set是为了在小朋友离开的时候,快速判断其是否还在等待队列中,而List则就是为了某个记录小朋友是第几个等待者。
2、模拟小朋友的来去情况:
  ①若小朋友第一次出现,则判断是否有空闲的小车
    A、有则他坐车,同时空闲小车数量 -1;
    B、没有则将其放入等待队列中。
  ②若小朋友第二次出现,判断其是否在等待队列中,
    A、是则表明其没有坐车就离开;
    B、若小朋友不在等待队列中,说明其在小车上,他走空出一个车,若还有小朋友在等待,则从等待队列中找出最早来的那个小朋友上车

在这里插入图片描述

代码:

public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	int cars = Integer.parseInt(scanner.nextLine());
	
	String[] split = scanner.nextLine().split(" ");
	int n = split.length;
	// 记录小朋友是否出现过,即用于判断小朋友是要等车还是离开
	Set<Integer> history = new HashSet<>();
	// 记录等待的小朋友
	Set<Integer> waitId = new HashSet<>();
	// 记录等待的小朋友是第几个等待者,因为坐车是按照先来先坐的次序
	List<int[]> wait = new ArrayList<>();
	int res = 0;
	// 记录等待的小朋友是第几个等待者
	int waitIndex = 0;

	for (int i = 0; i < n; i++) {
		int curChild = Integer.parseInt(split[i]);

		// 小朋友之前出现过——出现过代表小朋友离开
		if (history.contains(curChild)) {
			// 判断小朋友有没有做过车
			if (waitId.contains(curChild)) {
				// 小朋友在等待队列中
				res++;
				// 把小朋友从等待队列中删除
				waitId.remove(curChild);
				int removeIndex = 0;
				for (int j = 0; j < wait.size(); j++) {
					if (wait.get(j)[1] == curChild) {
						removeIndex = j;
						break;
					}
				}
				wait.remove(removeIndex);
			} else {
				// 小朋友坐过车
				// 如果还有小朋友,则让下一位小朋友过来坐车
				if (waitId.size() > 0) {
					Collections.sort(wait, (a, b)->a[1] - b[1]);
					int[] first = wait.remove(0);
					waitId.remove(first[1]);
				} else {
					cars++;
				}
				history.remove(curChild);
			}
		} else {
			history.add(curChild);
			// 看是否有空余的玩具车
			if (cars > 0) {
				cars--;
			} else {
				// 进入队列等待
				waitId.add(curChild);
				// waitIndex一直在增加,是为了防止在中途的时候,等待队列中某个小朋友离开,会导致等待队列乱序
				wait.add(new int[] {waitIndex++, curChild});
			}
		}
	}

	System.out.println(res);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值