LeetCode 2534. 通过门的时间

2534. 通过门的时间

n 个人,按从 0 到 n - 1 编号。现在有一扇门,每个人只能通过门进入或离开一次,耗时一秒。

给你一个 非递减顺序 排列的整数数组 arrival ,数组长度为 n ,其中 arrival[i] 是第 i 个人到达门前的时间。另给你一个长度为 n 的数组 state ,其中 state[i] 是 0 则表示第 i 个人希望进入这扇门,是 1 则表示 TA 想要离开这扇门。

如果 同时 有两个或更多人想要使用这扇门,则必须遵循以下规则:

  • 如果前一秒 没有 使用门,那么想要 离开 的人会先离开。
  • 如果前一秒使用门 进入 ,那么想要 进入 的人会先进入。
  • 如果前一秒使用门 离开 ,那么想要 离开 的人会先离开。
  • 如果多个人都想朝同一方向走(都进入或都离开),编号最小的人会先通过门。

返回一个长度为 n 的数组 answer ,其中 answer[i] 是第 i 个人通过门的时刻(秒)。

注意:

  • 每秒只有一个人可以通过门。
  • 为遵循上述规则,一个人可以在到达门附近后等待,而不通过门进入或离开。

示例 1:

输入:arrival = [0,1,1,2,4], state = [0,1,0,0,1]
输出:[0,3,1,2,4]
解释:每秒发生的情况如下:
- t = 0 :第 0 个人是唯一一个想要进入的人,所以 TA 可以直接进入。
- t = 1 :第 1 个人想要离开,第 2 个人想要进入。因为前一秒有人使用门进入,所以第 2 个人先进入。
- t = 2 :第 1 个人还是想要离开,第 3 个人想要进入。因为前一秒有人使用门进入,所以第 3 个人先进入。
- t = 3 :第 1 个人是唯一一个想要离开的人,所以 TA 可以直接离开。
- t = 4 :第 4 个人是唯一一个想要进入的人,所以 TA 可以直接离开。

示例 2:

输入:arrival = [0,0,0], state = [1,0,1]
输出:[0,2,1]
解释:每秒发生的情况如下:
- t = 0 :第 1 个人想要进入,但是第 0 个人和第 2 个人都想要离开。因为前一秒没有使用门,所以想要离开的人会先离开。又因为第 0 个人的编号更小,所以 TA 先离开。
- t = 1 :第 1 个人想要进入,第 2 个人想要离开。因为前一秒有人使用门离开,所以第 2 个人先离开。
- t = 2 :第 1 个人是唯一一个想要进入的人,所以 TA 可以直接进入。

提示:

  • n == arrival.length == state.length
  • 1 <= n <= 10^5
  • 0 <= arrival[i] <= n
  • arrival 按 非递减顺序 排列
  • state[i] 为 0 或 1

提示 1

Use a queue to store the people who want to enter or exit and their corresponding times.


提示 2

Simulate the process described in the statement and apply the 4 rules to the people crossing the door.

解法1:队列

算法逻辑

  1. 使用两个队列来分别存储想要进入和离开的人的索引,以及他们的到达时间。
  2. 使用一个变量status来跟踪门的上一次使用状态,可以是-1(未使用)、0(进入)或1(离开)。
  3. 使用一个循环来模拟时间的流逝,直到所有的人都通过了门。
  4. 在每个时间点,将所有在当前时间或之前到达的人加入到相应的队列中。
  5. 根据当前的status和队列中的元素来决定谁先通过门,并更新status和时间。

算法实现步骤

  1. 初始化answer数组来存储每个人通过门的时间,status为-1表示门上一秒未使用,index为当前处理到的人的索引,time为当前时间。
  2. 创建两个队列queues,分别用于存储想要进入和离开的人的索引。
  3. 使用一个外部循环,直到所有人都处理完毕或两个队列都为空。
  4. 在每个时间点,将所有在当前时间或之前到达的人加入到相应的队列中。
  5. 检查两个队列和status来决定谁先通过门:
    • 如果两个队列都不为空,根据status的值来决定是让想要离开的人先离开还是让想要进入的人先进入。
    • 如果只有一个队列非空,就让那个队列中的人们先通过门。
    • 如果两个队列都为空,将status设置为-1,
    • 增加时间。
  6. 更新answer数组,记录每个人通过门的时间。

为什么 else: status = -1

在代码中,else: status = -1这一行的作用是在没有其他人想要使用门的情况下,重置门的状态为未使用。这是必要的,因为根据题目的规则,如果前一秒门没有被使用,那么想要离开的人会先离开。通过将status设置为-1,我们可以确保在下一个人使用门之前,门的状态是未使用的。

Java版:

class Solution {
    public int[] timeTaken(int[] arrival, int[] state) {
        int n = arrival.length;
        int time = 0;
        int index = 0;
        int status = -1;
        Queue<Integer>[] queues = new Queue[2];
        for (int i = 0; i < 2; i++) {
            queues[i] = new ArrayDeque<Integer>();
        }
        int[] answer = new int[n];
        while (index < n || !queues[0].isEmpty() || !queues[1].isEmpty()) {
            while (index < n && arrival[index] <= time) {
                queues[state[index]].offer(index);
                index++;
            }
            if (!queues[0].isEmpty() && !queues[1].isEmpty()) {
                if (status == -1 || status == 1) {
                    answer[queues[1].poll()] = time;
                    status = 1;
                } else if (status == 0) {
                    answer[queues[0].poll()] = time;
                    status = 0;
                }
            } else if (!queues[0].isEmpty()) {
                answer[queues[0].poll()] = time;
                status = 0;
            } else if (!queues[1].isEmpty()) {
                answer[queues[1].poll()] = time;
                status = 1;
            } else {
                status = -1;
            }
            time++;
        }
        return answer;
    }
}

Python3版:

class Solution:
    def timeTaken(self, arrival: List[int], state: List[int]) -> List[int]:
        n = len(arrival)
        answer = [0] * n
        status = -1 
        index = 0
        time = 0
        queues = [ deque() for i in range(2)]
        while index < n or queues[0] or queues[1]:
            while index < n and arrival[index] <= time:
                queues[state[index]].append(index)
                index += 1
            if queues[0] and queues[1]:
                if status == -1 or status == 1:
                    answer[queues[1].popleft()] = time 
                    status = 1
                elif status == 0:
                    answer[queues[0].popleft()] = time
                    status = 0
            elif queues[0]:
                answer[queues[0].popleft()] = time
                status = 0
            elif queues[1]:
                answer[queues[1].popleft()] = time 
                status = 1
            else:
                status = -1
            time += 1
        return answer

复杂度分析

  • 时间复杂度:O(n),其中n是人数。因为每个人只会被处理一次,无论是加入队列还是从队列中取出。
  • 空间复杂度:O(n),需要存储所有想要进入或离开的人的索引。
  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值