A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skylineformed by these buildings collectively (Figure B).
The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi]
, where Li
and Ri
are the x coordinates of the left and right edge of the ith building, respectively, and Hi
is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX
, 0 < Hi ≤ INT_MAX
, and Ri - Li > 0
. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.
For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ]
.
/* 在轮廓上进行遍历 pre cur 分别为之前和当前的最高高度 最高高度发生变化时即是拐点(用一根平行x的直线进行line sweep)
* 扫描时如果是左边界 入队 如果是右边界就删除 同时和之前的高度比较
* 扫描顺序!!重要
* 1.按x从小到大扫描
* 2. 如果x值相同 若是在上升扫描(即左边界 )要先扫描到高的位置(不然低的先进入会多一个拐点)
* 在右边界时 先扫描低的位置 (不然高的位置先出队 会多一个拐点)
* 左边界比右边界优先入队 (插入先于删除)
* 发现如果把左边界设为负数 2的条件都能满足
* 构建一个最大堆 排序方法为: 按x从大到小 若x相同 且是左边界 y值小的在上面 右边界
*
* */
class Solution {
public:
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
vector<vector<int>> ret;
multiset<int> s; // 基于红黑树的 根节点的值最小 begin()返回第一个节点即最小值 rbegin()返回最后一个节点即最大值
vector<pair<int, int>> tmp; // 存放x 及对应的高度
for(auto &b : buildings){
tmp.emplace_back(b[0], -b[2]);
tmp.emplace_back(b[1], b[2]);
}
sort(tmp.begin(), tmp.end());
// 开始扫描 每次左边界入set 右边界从set中删除 最高高度变化即为拐点
int pre=0, cur=0;
//cout<<tmp[0].first;
s.insert(0);
for(auto & v:tmp){
if(v.second<0) s.insert(-v.second);
else s.erase(s.find(v.second));// multiset 不能erase(val)会删除所有的 只要找到一个删除就好
cur = *s.rbegin();
if(cur != pre){
ret.push_back({v.first, cur});
pre = cur;
}
}
return ret;
}
};