刷题的日常-无法吃午餐的学生数量

79 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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;
    }
}

a29cf614d04af4183d9e679ac4c79b2.jpg