LeetCode每日一题(The Number of the Smallest Unoccupied Chair)

There is a party where n friends numbered from 0 to n - 1 are attending. There is an infinite number of chairs in this party that are numbered from 0 to infinity. When a friend arrives at the party, they sit on the unoccupied chair with the smallest number.

For example, if chairs 0, 1, and 5 are occupied when a friend comes, they will sit on chair number 2.
When a friend leaves the party, their chair becomes unoccupied at the moment they leave. If another friend arrives at that same moment, they can sit in that chair.

You are given a 0-indexed 2D integer array times where times[i] = [arrivali, leavingi], indicating the arrival and leaving times of the ith friend respectively, and an integer targetFriend. All arrival times are distinct.

Return the chair number that the friend numbered targetFriend will sit on.

Example 1:

Input: times = [[1,4],[2,3],[4,6]], targetFriend = 1
Output: 1

Explanation:

  • Friend 0 arrives at time 1 and sits on chair 0.
  • Friend 1 arrives at time 2 and sits on chair 1.
  • Friend 1 leaves at time 3 and chair 1 becomes empty.
  • Friend 0 leaves at time 4 and chair 0 becomes empty.
  • Friend 2 arrives at time 4 and sits on chair 0.
    Since friend 1 sat on chair 1, we return 1.

Example 2:

Input: times = [[3,10],[1,5],[2,6]], targetFriend = 0
Output: 2

Explanation:

  • Friend 1 arrives at time 1 and sits on chair 0.
  • Friend 2 arrives at time 2 and sits on chair 1.
  • Friend 0 arrives at time 3 and sits on chair 2.
  • Friend 1 leaves at time 5 and chair 0 becomes empty.
  • Friend 2 leaves at time 6 and chair 1 becomes empty.
  • Friend 0 leaves at time 10 and chair 2 becomes empty. Since friend 0 sat on chair 2, we return 2.

Constraints:

  • n == times.length
  • 2 <= n <= 104
  • times[i].length == 2
  • 1 <= arrivali < leavingi <= 105
  • 0 <= targetFriend <= n - 1
  • Each arrivali time is distinct.

按arrival time的时间轴来挨个处理每个friend, 在这个friend入座之前,我们先要清理已经达到或者超过leave time的seat, 清理完成之后在free seats中挑一个最靠前的,如果这个friend是我们要找的人,那直接返回seat, 如果不是,则把当前friend的leave time记录下来。然后处理下一个friend。

整个流程其实就像上面说的这么简单,重点是选择合适的数据结构来保存leave time和seat的信息。seat我们选择用一个BinaryHeap来保存所有的空着的座位(free_seats), 有朋友来就从中pop一个最小的seat出来, 有人离开则把seat push进来就可以了。leave times比较复杂一点,一方面同一个leave time能会有多个人离开,另一方面,我们实际清理seats的时候其实是新的friend进来的时候,所以此时可能已经有多个leave times的friends需要离开。所以,我们用一个HashMap来保存leave time与seats的对应关系,另外用一个BinaryHeap来保存单独的时间点,相当于HashMap的有序索引。这样上面的整个流程就可以顺利的进行了。


代码实现(Rust):

use std::collections::{ HashMap, BinaryHeap };
use std::cmp::Reverse;


impl Solution {
    pub fn smallest_chair(mut times: Vec<Vec<i32>>, target_friend: i32) -> i32 {
        let mut leave_times: BinaryHeap<Reverse<i32>> = BinaryHeap::new();
        let mut leave_schedule: HashMap<i32, Vec<i32>> =  HashMap::new();
        let mut free_seats: BinaryHeap<Reverse<i32>> = (0..10000).into_iter().map(|v| Reverse(v)).collect();
        let arrival_time = times[target_friend as usize][0];
        times.sort_by_key(|v| v[0]);
        for t in times {
            while let Some(Reverse(lt)) = leave_times.pop() {
                if lt <= t[0] {
                    let leaves = leave_schedule.remove(&lt).unwrap();
                    leaves.into_iter().for_each(|v| free_seats.push(Reverse(v)));
                } else {
                    leave_times.push(Reverse(lt));
                    break;
                }
            }
            let seat = free_seats.pop().unwrap().0;
            if t[0] == arrival_time {
                return seat;
            }
            if leave_schedule.contains_key(&t[1]) {
                leave_schedule.get_mut(&t[1]).unwrap().push(seat);
            } else {
                leave_times.push(Reverse(t[1]));
                leave_schedule.insert(t[1], vec![seat]);
            }
        }
        unreachable!()
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值