【LeetCode】218. 天际线问题 结题报告 (C++)

原题地址:https://leetcode-cn.com/problems/the-skyline-problem/

题目描述:

城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。现在,假设您获得了城市风光照片(图A)上显示的所有建筑物的位置和高度,请编写一个程序以输出由这些建筑物形成的天际线(图B)。

Buildings  Skyline Contour
每个建筑物的几何信息用三元组 [Li,Ri,Hi] 表示,其中 Li 和 Ri 分别是第 i 座建筑物左右边缘的 x 坐标,Hi 是其高度。可以保证 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX 和 Ri - Li > 0。您可以假设所有建筑物都是在绝对平坦且高度为 0 的表面上的完美矩形。

例如,图A中所有建筑物的尺寸记录为:[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] 。

输出是以 [ [x1,y1], [x2, y2], [x3, y3], ... ] 格式的“关键点”(图B中的红点)的列表,它们唯一地定义了天际线。关键点是水平线段的左端点。请注意,最右侧建筑物的最后一个关键点仅用于标记天际线的终点,并始终为零高度。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。

例如,图B中的天际线应该表示为:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]。

说明:

任何输入列表中的建筑物数量保证在 [0, 10000] 范围内。
输入列表已经按升序排列在左边的 x 位置 Li 。
输出列表必须按 x 位排序。
输出天际线中不得有连续的相同高度的水平线。例如 [...[2 3], [4 5], [7 5], [11 5], [12 7]...] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[...[2 3], [4 5], [12 7], ...]

解题方案:

题目给出的提示是堆,树状数组,分治算法和线段树。

网上的思路参考地址:https://blog.csdn.net/zycxnanwang/article/details/82989651

可以看成一个归并问题
切分的时候,如果剩一个元素,返回它表示的两个轮廓点,如果为空,返回空
合并是重点:
维护两个变量:h1,h2 h1表示左半部分当前位置高度,h2表示右半部分当前位置高度
如果当前位置左半部分横坐标更小,就更新h1,从左半部分选元素;
如果当前位置右半部分横坐标更小,就更新h2,从右半部分选元素;
如果一样大,就更新h1,h2,从左(或右)半部分选元素
当向结果中插入点时,只有和结果中最后一个点高度不同的点才能插入到结果里
且一直使用高度max(h1,h2)。
当某一部分全部访问完,就将另一部分直接插入结果里(注意高度不要与之前重复)。

下面代码使用了multiset。mutiset:多重集合 和set最大的区别就是,它可以插入重复的元素,

如果删除的话,相同的也一起删除了;

如果查找的话,返回该元素的迭代器的位置,若有相同,返回第一个元素的地址;

其他使用和set基本类似。

代码:

class Solution {
public:
    vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
        vector<pair<int, int>> h, res;
        multiset<int> m;
        int pre = 0, cur = 0;
        for (auto &a : buildings) {
            h.push_back({a[0], -a[2]});
            h.push_back({a[1], a[2]});
        }
        sort(h.begin(), h.end());
        m.insert(0);
        for (auto &a : h) {
            if (a.second < 0) 
                m.insert(-a.second);
            else 
                m.erase(m.find(a.second));
            cur = *m.rbegin();
            if (cur != pre) {
                res.push_back({a.first, cur});
                pre = cur;
            }
        }
        return res;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_32805671/article/details/84261853