扫描线。
用大根堆来维护已经扫过的建筑物的高度。将所有建筑物按横坐标分为两组,左侧的边赋值为1,右侧的边赋值为-1,分别表示扫到这个边时,这个建筑物是应当入堆,还是出堆。然后对边进行排序,按横坐标升序,边的值降序,高度降序的优先级进行排列。之后枚举所有边,每当操作边出堆入堆的时候,如果最高高度发生了变化,则需要记录答案。
class Solution {
public:
vector<vector<int>> getSkyline(vector<vector<int>>& buildings){
int n=buildings.size();
vector<vector<int>> ans;
vector<vector<int>> g;
vector<int> vis(n,0);
for(int i=0;i<n;i++){
g.push_back({buildings[i][0],buildings[i][2],1,i});
g.push_back({buildings[i][1],buildings[i][2],-1,i});
}
sort(g.begin(),g.end(),[](const auto &a,const auto &b){
if(a[0]==b[0]){
if(a[2]==b[2]) return a[1]>b[1];
else return a[2]>b[2];
}
return a[0]<b[0];
});
priority_queue<pair<int,int>> q;
q.push({0,-1});
int mx=0;
for(int i=0;i<n*2;i++){
if(g[i][2]==1){
q.push({g[i][1],g[i][3]});
if(mx<q.top().first){
mx=q.top().first;
ans.push_back({g[i][0],mx});
}
}else{
vis[g[i][3]]=1;
while(i+1<n*2&&g[i+1][2]==-1&&g[i+1][0]==g[i][0]){
i++;
vis[g[i][3]]=1;
}
while(q.size()>1&&vis[q.top().second]) q.pop();
if(mx>q.top().first){
mx=q.top().first;
ans.push_back({g[i][0],mx});
}
}
}
return ans;
}
};
时间复杂度:O(nlogn),n为建筑物数量。
空间复杂度:O(n)。