[leetcode] 218.The Skyline Problem

题目:
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).
[leetcode] 218.The Skyline Problem_第1张图片
[leetcode] 218.The Skyline Problem_第2张图片

Buildings 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], …]

题意:
题目的意思是找出这些长方形的建筑的一些边际点。如图A,B所示,找的其实是沿着x轴从左往右扫描时出现的矩形最高点的开始位置(即矩形的右上角)。比如第一个位置是[2,10],这是整个图形的开始,所以该点是当前开始时的最高点。继续往后扫描到[3,15],接下来的长方形的高会变化到15,所以这个左上角的点也要保存。继续扫描下去,当x=7的时候,图形的高度会从当前的最高高度15降到次高高度12,所以将[7,12]这个作为接下来矩形的最大高度保存。当扫描到12时,前面一块的长方形已经全部结束。这个时候需要保存这个右下角的点即[12,0]。
思路:
从上面对题目的分析,我们可以看出,我们需要保存的是扫描到当前位置时,图形中的最高位置。如果遇到一个更高的位置,那么需要加入这个左上角的位置。如果从这个最高位置出来了,那么需要判断接下来图形的最高位置是什么,因为可能多个长方形都是一个高度,所以次高位置跟最高位置可能相同。使用堆来完成。我们可以使用STL中multimap来完成。
整个过程首先是将这些点按照x轴进行排列,然后依次扫描这些点。这些点需要区分为是矩形的左边的边还是右边的那条边。从而决定是将这个最大高度加入,还是将最高高度去除。
代码如下:
需要考虑的边际情况比较多。

struct myCompare {
    bool operator()(vector<int> a, vector<int> b) {
        return a[0] < b[0];
    }
}mycompare;

struct keyComp {
    bool operator()(int a, int b) {
        return a > b;
    }
};
class Solution {
public:
    vectorint, int>> getSkyline(vector<vector<int>>& buildings) {
        vectorint, int>> result;
        if (buildings.empty())return result;
        vector<vector<int>> x_height;
        for (auto a : buildings) {
            vector<int> t1 = { a[0], a[2], 0 };
            x_height.push_back(t1);
            vector<int> t2 = { a[1], a[2], 1 };
            x_height.push_back(t2);
        }
        sort(x_height.begin(), x_height.end(), mycompare);
        multimap<int, int, keyComp> heights;
        int size = x_height.size();
        int heights_size = 0;
        for (int i = 0; i < size; i++) {
            switch (x_height[i][2]) {
            case 0: {
                        if (heights.empty() || x_height[i][1] > (heights.begin())->first) {
                            if ((result.size() == 1 && x_height[i][0] == result.back().first && x_height[i][1] > result.back().second) ||
                                (result.size() > 1 && x_height[i][0] == result.back().first)) {
                                result.pop_back();
                                if (result.empty() || (result.size() >= 1 && x_height[i][1] != result.back().second))
                                    result.push_back(pair<int, int>(x_height[i][0], x_height[i][1]));
                            }
                            else if (result.empty() || (x_height[i][1] != result.back().second))
                                result.push_back(pair<int, int>(x_height[i][0], x_height[i][1]));

                        }
                        heights.insert(pair<int, int>(x_height[i][1], 1));
                        heights_size++;
            }break;
            case 1: {
                        if (heights_size == 1) {
                            if (x_height[i][0] == result.back().first)result.pop_back();
                            result.push_back(pair<int, int>(x_height[i][0], 0));
                        }
                        else if (x_height[i][1] == (heights.begin())->first && (heights.begin())->first != (++heights.begin())->first) {

                            if (result.empty() || (++heights.begin())->first != result.back().second){
                                if(!(!result.empty() && x_height[i][0] == (result.back().first)))
                                    result.push_back(pair<int, int>(x_height[i][0], (++heights.begin())->first));
                            }

                        }
                        heights.erase(heights.find(x_height[i][1]));
                        heights_size--;

            }break;
            }
        }
        return result;
    }
};

你可能感兴趣的:(leetcode,堆)