LeetCode 1845.座位预约管理系统

请你设计一个管理 n 个座位预约的系统,座位编号从 1 到 n 。

请你实现 SeatManager 类:

SeatManager(int n) 初始化一个 SeatManager 对象,它管理从 1 到 n 编号的 n 个座位。所有座位初始都是可预约的。
int reserve() 返回可以预约座位的 最小编号 ,此座位变为不可预约。
void unreserve(int seatNumber) 将给定编号 seatNumber 对应的座位变成可以预约。

示例 1:

输入:
[“SeatManager”, “reserve”, “reserve”, “unreserve”, “reserve”, “reserve”, “reserve”, “reserve”, “unreserve”]
[[5], [], [], [2], [], [], [], [], [5]]
输出:
[null, 1, 2, null, 2, 3, 4, 5, null]

解释:
SeatManager seatManager = new SeatManager(5); // 初始化 SeatManager ,有 5 个座位。
seatManager.reserve(); // 所有座位都可以预约,所以返回最小编号的座位,也就是 1 。
seatManager.reserve(); // 可以预约的座位为 [2,3,4,5] ,返回最小编号的座位,也就是 2 。
seatManager.unreserve(2); // 将座位 2 变为可以预约,现在可预约的座位为 [2,3,4,5] 。
seatManager.reserve(); // 可以预约的座位为 [2,3,4,5] ,返回最小编号的座位,也就是 2 。
seatManager.reserve(); // 可以预约的座位为 [3,4,5] ,返回最小编号的座位,也就是 3 。
seatManager.reserve(); // 可以预约的座位为 [4,5] ,返回最小编号的座位,也就是 4 。
seatManager.reserve(); // 唯一可以预约的是座位 5 ,所以返回 5 。
seatManager.unreserve(5); // 将座位 5 变为可以预约,现在可预约的座位为 [5] 。

提示:

1 <= n <= 105^55
1 <= seatNumber <= n
每一次对 reserve 的调用,题目保证至少存在一个可以预约的座位。
每一次对 unreserve 的调用,题目保证 seatNumber 在调用函数前都是被预约状态。
对 reserve 和 unreserve 的调用 总共 不超过 105^55 次。

法一:我们可以把初始的n个座位用小顶堆表示,这样每次预约直接拿堆顶的座位即可:

class SeatManager {
public:
    SeatManager(int n) {
        h.resize(n);

        for (int i = 1; i <= n; ++i) {
            h[i - 1] = i;
        }

        make_heap(h.begin(), h.end(), greater());
    }
    
    int reserve() {
        int smallest = h[0];

        pop_heap(h.begin(), h.end(), greater());
        h.pop_back();

        return smallest;
    }
    
    void unreserve(int seatNumber) {
        h.push_back(seatNumber);
        push_heap(h.begin(), h.end(), greater());
    }

private:
    vector<int> h;
};

/**
 * Your SeatManager object will be instantiated and called as such:
 * SeatManager* obj = new SeatManager(n);
 * int param_1 = obj->reserve();
 * obj->unreserve(seatNumber);
 */

如果一共有n个座位,则此算法构造函数的时间复杂度为O(n),reserve和unreserve方法的时间复杂度为O(logn),空间复杂度为O(n)。

法二:法一中,如果座位数过多,可能会爆内存,我们可以用小顶堆管理已经分配过的座位,再维护一个分配过的最大座位号m,如果预约时发现小顶堆为空,就分配m+1号座位,否则分配堆顶座位:

class SeatManager {
public:
    SeatManager(int n) {
        
    }
    
    int reserve() {
        if (h.empty()) {
            return ++maxSeat;
        }

        int ret = h[0];
        pop_heap(h.begin(), h.end(), greater());
        h.pop_back();

        return ret;
    }
    
    void unreserve(int seatNumber) {
        h.push_back(seatNumber);
        push_heap(h.begin(), h.end(), greater());
    }

private:
    vector<int> h;
    int maxSeat = 0;
};

/**
 * Your SeatManager object will be instantiated and called as such:
 * SeatManager* obj = new SeatManager(n);
 * int param_1 = obj->reserve();
 * obj->unreserve(seatNumber);
 */

如果有q个预约请求,则此算法reserve和unreserve方法的时间复杂度为O(logq),空间复杂度为O(q)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值