美文网首页
218. The Skyline Problem解题报告

218. The Skyline Problem解题报告

作者: 黑山老水 | 来源:发表于2019-05-30 15:49 被阅读0次

    Description:

    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 skyline formed by these buildings collectively (Figure B).

    [ Buildings

    ](https://leetcode.com/static/images/problemset/skyline1.jpg)

    Skyline Contour

    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] ].

    The output is a list of "key points" (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.

    For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ].

    Notes:

    • The number of buildings in any input list is guaranteed to be in the range [0, 10000].
    • The input list is already sorted in ascending order by the left x position Li.
    • The output list must be sorted by the x position.
    • There must be no consecutive horizontal lines of equal height in the output skyline. For instance, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...[2 3], [4 5], [12 7], ...]

    Link:

    https://leetcode.com/problems/the-skyline-problem/

    解题方法:

    通过观察可以知道,根据水平轴的推移,当前的水平坐标的高度出现变化的时候,我们需要记录下点。
    所以,

    1. 首先应该把所有的建筑起始点终止点都记录下来,起始点的高度为正,终止点的高度为负,这样就可以做出区分。
    2. 然后对所有的点进行排序,当处在同一坐标下,高度大的排在前面,否则按照水平坐标从小到大排,这样有一个好处就是:当碰到input是[[0,2,3],[2,5,3]]的时候,第二个(2,3)会排在(2,-3)前面,就避免了相连线段在记录的时候断开的情况。同时,针对input是[[0,2,3],[1,2,1],[2,4,1],[2,5,3]],也会避免我们先接触到比较矮的建筑。
    3. 用一个tree map来记录当前的水平坐标上的高度,当我们碰到一个初始点,如果当前建筑最高的高度都不如这个初始点的高度,记录这个坐标。当我们碰到一个终止点的时候,应该把对应的高度-1,如果这个高度已经没有了,应该把这个高度从tree map中移除。并且,在碰到一个终止点之后,tree map的最高高度有变化,说明之前最高的建筑已经走完了,需要记录下目前坐标和第二高的高度。

    Tips:

    本题LeetCode的答案是有问题的:
    当input为[[0,2,3],[2,5,3]]时,

    image.png
    说明本题答案默认两个高度相同,收尾相连的建筑是同一个。
    然而,当input为[[0,2,3],[1,2,1],[2,4,1],[2,5,3]]的时候,
    image.png
    LeetCode的答案又出现了问题。

    Time Complexity:

    nlogn

    完整代码:

    class Solution {
    public:
        vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
            vector<vector<int>> ans;
            int size = buildings.size();
            if(!size)
                return ans;
            vector<vector<int>> points;
            for(auto building: buildings) {
                points.push_back({building[0], building[2]});
                points.push_back({building[1], -building[2]});
            }
            sort(points.begin(), points.end(), [](vector<int>& a, vector<int>& b){
                if(a[0] < b[0] || (a[0] == b[0] && a[1] > b[1]))
                    return true;
                else
                    return false;
            });
            map<int, int, greater<int>> heights;
            heights[0] = 1;
            for(auto point: points) {
                if(point[1] > 0) {
                    if(point[1] > heights.begin()->first) {
                        ans.push_back({point[0], point[1]});
                    }
                    heights[point[1]]++;
                } else {
                    heights[abs(point[1])]--;
                    if(heights[abs(point[1])] == 0) {
                        heights.erase(abs(point[1]));
                    }
                    if(abs(point[1]) > heights.begin()->first) {
                        ans.push_back({point[0], heights.begin()->first});
                    }
                }
            }
            return ans;
        }
    };
    

    相关文章

      网友评论

          本文标题:218. The Skyline Problem解题报告

          本文链接:https://www.haomeiwen.com/subject/kqnvattx.html