leetcode 218 天际线问题

初次见到确实是比较困难的问题。解决问题的关键在于抽象出答案中水平线段的端点一定是某一建筑的左端点或者右端点,而如果是右端点作为端点,则该建筑的高度对于这个水平线段并不产生影响(最后一个建筑后的高度为0的天际线就是一个例子)。所以可以考虑遍历所有的端点,对某一个端点而言,考虑所有包含该端点的建筑,其中最高的自然就是以该端点为起始点的天际线的高度,这一部分的比较可以使用优先队列来完成。这里还会用到一个延迟删除的技巧,对于某一个端点,并不需要删除所有不满足要求的建筑,而是只要当前队列中的最大值的建筑包含该端点即可,若当前最大值并不包含该端点,则弹出该建筑,重复该过程知道当前top节点满足要求。而在建筑进入优先队列之后,判断是否需要弹出队列的依据只有该建筑的右端点与高度值,所以优先队列中只需要维护一个二元组即可。贴代码

 1 class Solution {
 2 public:
 3     vector<vector<int>> getSkyline(vector<vector<int>>& buildings) 
 4     {
 5         auto cmp = [](const pair<int, int>& a, const pair<int, int>& b) -> bool { return a.second < b.second; };
 6         priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(cmp)> que(cmp);
 7         vector<int> boundaries;
 8         for(auto& building:buildings)
 9         {
10             boundaries.emplace_back(building[0]);
11             boundaries.emplace_back(building[1]);
12         }                
13         sort(boundaries.begin(),boundaries.end());
14         
15         vector<vector<int>> ret;
16         int n = buildings.size();
17         int index = 0;
18         for(auto boundary:boundaries)
19         {
20             //建筑处于当前范围内
21             while(index<n && boundary>=buildings[index][0])
22             {
23                 que.emplace(buildings[index][1],buildings[index][2]);
24                 index++;
25             }
26             while(!que.empty() && que.top().first<=boundary)
27             que.pop();
28             int maxn = que.empty()?0:que.top().second;
29             if(ret.size() == 0 || ret.back()[1]!=maxn)
30             ret.push_back({boundary,maxn});
31         }
32         return ret;
33     }
34 };

 

posted @ 2021-11-06 12:02  zhaohhhh  阅读(57)  评论(0)    收藏  举报