持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情
刷题的日常-2022年10月19号
一天一题,保持脑子清爽
无法吃午餐的学生数量
来自leetcode的 1700 题,题意如下:
学校的自助午餐提供圆形和方形的三明治,分别用数字0和1表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。 餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个栈里,每一轮:
- 如果队列最前面的学生喜欢栈顶的三明治,那么会拿走它并离开队列。
- 否则,这名学生会放弃这个三明治并回到队列的尾部。
- 这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。
给你两个整数数组students 和sandwiches,其中sandwiches[i]是栈里面第i个三明治的类型(i = 0是栈的顶部),students[j]是初始队列里第j名学生对三明治的喜好(j = 0是队列的最开始位置)。请你返回无法吃午餐的学生数量。
理解题意
通过题意,我们可以将信息整理如下:
- 题目给定两个数组
- 要求我们对数组进行匹配,一个是栈,一个是队列
- 队列头如果可以和栈头匹配,则削去栈顶元素和队列元素
- 如果不匹配,则队头元素放到队尾,继续进行以上操作
- 要求返回最后栈里面无法削去的元素个数
做题思路
第一个思路可以是模拟,直接以栈和队列的操作对题意进行操作,如果最后没办法削去,则返回栈内剩余元素个数。但是这里不采用模拟的思路。因为队列的元素和循环无关,之和栈顶元素有关,所以我们匹配栈顶元素时,其实只要对应匹配的队列元素存在就行,所以我们可以先统计不同三明治的个数,然后对栈顶元素进行匹配,如果匹配的队列元素不为0,则可以进行削去,最后返回剩下的元素个数即可。
代码实现
代码实现如下,因为只需要遍历一次,所以时间复杂度为O(n):
public class Solution {
public int countStudents(int[] students, int[] sandwiches) {
int cntZ = 0, cntO = 0;
for (int num : students) {
cntZ += num == 0 ? 1 : 0;
cntO += num == 1 ? 1 : 0;
}
for (int sandwich : sandwiches) {
if (sandwich == 1 && cntO > 0) {
cntO--;
continue;
}
if (sandwich == 0 && cntZ > 0) {
cntZ--;
continue;
}
break;
}
return cntZ + cntO;
}
}