力扣刷题——855. 考场就座

题目要求进入考场的学生必须是离别人最远的,那么可以想到用一个最大堆维护区间长度,这样每次插入都只需要在堆头部插入新区间即可。
要注意,当区间的一端不在首尾时,区间长度除以2是新加入的学生距离两边的距离;而区间有一端在首尾时,为了方便计算,令左端点为-1,右端点为N,这样,区间长度就等于区间的右端点 - 左端点 - 1
在结构体中又加入了哈希表,分别存储座位的左右座位号,方便删除区间,这种做法有点类似链表。
最后在实现的过程中使用了表达式设定堆的排序方式,确保类的封装性,代码如下:

class ExamRoom {
public:
    int N;
    set<pair<int, int>, std::function<bool(const std::pair<int, int>&, const std::pair<int, int>&)>> interval;
    unordered_map<int, int> left;
    unordered_map<int, int> right;

    ExamRoom(int n) : N(n), interval(compare__())
    {
        
    }

    std::function<bool(const std::pair<int, int>&, const std::pair<int, int>&)> compare__() const 
    {
        return [this](const std::pair<int, int>& a, const std::pair<int, int>& b) 
        {
            int d1, d2;
            if(a.first == -1 || a.second == N)
                d1 = a.second - a.first - 1;
            else
                d1 = (a.second - a.first) / 2;
            
            if(b. first == -1 || b. second == N)
                d2 = b.second - b.first - 1;
            else
                d2 = (b.second - b.first) / 2;

            return d1 == d2 ? a.first < b.first : d1 > d2;
        };
    }

    int seat() 
    {
        if(interval.empty())
        {
            interval.insert({-1, 0});
            interval.insert({0, N});
            left[0] = -1;
            right[-1] = 0;
            left[N] = 0;
            right[0] = N;
            return 0;
        }

        pair<int, int> tem = *interval.begin();
        int p;
        if(tem.first == -1)
        {
            p = 0;
        }
        else if(tem.second == N)
        {
            p = N - 1;
        }
        else
        {
            p = (tem.first + tem.second) / 2;
        }
        
        interval.erase(interval.begin());
        interval.insert({tem.first, p});
        interval.insert({p, tem.second});
        left[p] = tem.first;
        right[p] = tem.second;
        left[tem.second] = p;
        right[tem.first] = p;
        return p;
        
    }
    
    void leave(int p) 
    {
        int a = left[p];
        int b = right[p];
        interval.erase({a, p});
        interval.erase({p, b});
        interval.insert({a, b});
        left.erase(p);
        right.erase(p);
        right[a] = b;
        left[b] = a;
    }
};
posted @ 2024-12-25 16:31  SuzumiyaYui  阅读(11)  评论(0)    收藏  举报