LeetCode 218. 天际线问题 (扫描线+优先队列)

扫描线+优先队列 https://leetcode-cn.com/problems/the-skyline-problem/solution/tian-ji-xian-wen-ti-by-leetcode-solution-ozse/

先把所有横坐标排序,然后把建筑按横坐标排序。设定每个建筑都包含左不包含有  [left,right) 这样。然后对于每一个横坐标都先在优先队列压入包含它的建筑

然后再从最高的点开始找,如何不包含该横坐标就弹出。然后剩下的建筑中,都是包含该横坐标的,找最高的那个就是关键点。

要学习一下优先队列自定义排序的写法。

class Solution {
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
        // 优先队列保存当前最大高度
        // 优先队列 按高度排序
        auto cmp = [](const pair<int, int>& a, const pair<int, int>& b) -> bool { return a.second < b.second; };
        priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> q(cmp);

        vector<int> boundaries; // 保存所有横坐标
        for (auto &b: buildings) {
            boundaries.push_back(b[0]);
            boundaries.push_back(b[1]);
        }
        sort(boundaries.begin(), boundaries.end()); // 横坐标从小到达排序

        // buildings 按 lefti 非递减排序 不需要再次排序
        vector<vector<int>> ret;
        int n = buildings.size(), idx = 0;
        for (auto & b: boundaries) {
            while (idx < n && buildings[idx][0] <= b) {
                q.emplace(buildings[idx][1], buildings[idx][2]);
                idx++;
            }
            while (!q.empty() && q.top().first <= b) {
                q.pop();
            }
            int maxh = q.empty() ? 0 : q.top().second;
            if (ret.empty() || maxh != ret.back()[1]) {
                ret.push_back({b, maxh});
            }
        }

        return ret;        
    }
};

 

posted @ 2021-12-11 11:52  我不吃饼干呀  阅读(118)  评论(0编辑  收藏  举报