天际线问题
本题需要用到扫描线算法,不需要线段树(不需要区间查询)。
扫描线算法适合求由若干个矩形叠成的不规则图形的周长、面积问题。
本题需要输出所有横边的左端点,需要考虑一些边界情况。
首先需要找出所有竖边,求出所有竖边的顶点坐标存入一个 pair(pair 是双关键字排序),然后对这些坐标点进行排序。
排序时对于重合的两条竖边(横坐标一样,纵坐标不同)要分情况讨论:
假设两个点的坐标分别为 A(x, y)、B(x, z)。
- A 点是某个矩形的左端点,B 点是某个矩形的左端点。纵坐标高的排在前面。
- A 点是某个矩形的右端点,B 点是某个矩形的右端点。纵坐标低的排在前面。
- A 点是某个矩形的左端点,B 点是某个矩形的右端点。A 点排在前面。
- A 点是某个矩形的右端点,B 点是某个矩形的左端点。B 点排在前面。
总之,左端点重合,先大后小,右端点重合,先小后大,左右端点重合,先左后右。
在 pair 里面存左端点的时候,存负值。然后调用 sort 的时候就能自动实现上述排序规则。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class Solution { public: vector<vector<int>> getSkyline(vector<vector<int>> &buildings) { vector<vector<int>> res; vector<pair<int, int>> points; multiset<int> heights;
for (auto &b : buildings) { points.push_back({b[0], -b[2]}); points.push_back({b[1], b[2]}); } sort(points.begin(), points.end()); heights.insert(0); for (auto &p : points) { int x = p.first, h = abs(p.second); if (p.second < 0) { if (h > *heights.rbegin()) { res.push_back({x, h}); } heights.insert(h); } else { heights.erase(heights.find(h)); if (h > *heights.rbegin()) { res.push_back({x, *heights.rbegin()}); } } } return res; } };
|