141 lines
7.3 KiB
C++
141 lines
7.3 KiB
C++
![]() |
// Source : https://leetcode.com/problems/the-skyline-problem/
|
|||
|
// Author : Hao Chen
|
|||
|
// Date : 2015-06-11
|
|||
|
|
|||
|
/**********************************************************************************
|
|||
|
*
|
|||
|
* 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).
|
|||
|
*
|
|||
|
* ^ ^
|
|||
|
* | |
|
|||
|
* | |
|
|||
|
* | +-----+ | O-----+
|
|||
|
* | | | | | |
|
|||
|
* | | | | | |
|
|||
|
* | | +--+------+ | | O------+
|
|||
|
* | | | | | | |
|
|||
|
* | +-+--+----+ | +------+ | O-+ | O------+
|
|||
|
* | | | | | | | | | | |
|
|||
|
* | | | | | +-+--+ | | | | O--+
|
|||
|
* | | | | | | | | | | | |
|
|||
|
* | | | | | | | | | | | |
|
|||
|
* | | | | | | | | | | | |
|
|||
|
* | | | | | | | | | | | |
|
|||
|
* +--+---------+----+---+----+----+---> +--+--------------O---+---------O--->
|
|||
|
*
|
|||
|
* https://leetcode.com/static/images/problemset/skyline1.jpg
|
|||
|
* https://leetcode.com/static/images/problemset/skyline2.jpg
|
|||
|
*
|
|||
|
* 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 , 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], ...]
|
|||
|
*
|
|||
|
* Credits: Special thanks to @stellari for adding this problem,
|
|||
|
* creating these two awesome images and all test cases.
|
|||
|
*
|
|||
|
**********************************************************************************/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* Sweep line with max-heap
|
|||
|
* ------------------------
|
|||
|
* Notice that "key points" are either the left or right edges of the buildings.
|
|||
|
*
|
|||
|
* Therefore, we first obtain both the edges of all the N buildings, and store the 2N edges in a sorted array.
|
|||
|
* Maintain a max-heap of building heights while scanning through the edge array:
|
|||
|
* 1) If the current edge is a left edge, then add the height of its associated building to the max-heap;
|
|||
|
* 2) If the edge is a right one, remove the associated height from the heap.
|
|||
|
*
|
|||
|
* Then we take the top value of the heap (yi) as the maximum height at the current edge position (xi).
|
|||
|
* Now (xi, yi) is a potential key point.
|
|||
|
*
|
|||
|
* If yi is the same as the height of the last key point in the result list, it means that this key point
|
|||
|
* is not a REAL key point, but rather a horizontal continuation of the last point, so it should be discarded;
|
|||
|
*
|
|||
|
* otherwise, we add (xi,yi) to the result list because it is a real key point.
|
|||
|
*
|
|||
|
* Repeat this process until all the edges are checked.
|
|||
|
*
|
|||
|
* It takes O(NlogN) time to sort the edge array. For each of the 2N edges,
|
|||
|
* it takes O(1) time to query the maximum height but O(logN) time to add
|
|||
|
* or remove elements. Overall, this solution takes O(NlogN) time.
|
|||
|
*/
|
|||
|
class Solution {
|
|||
|
public:
|
|||
|
|
|||
|
vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
|
|||
|
vector< pair<int, int> > edges;
|
|||
|
|
|||
|
//put all of edge into a vector
|
|||
|
//set left edge as negtive, right edge as positive
|
|||
|
//so, when we sort the edges,
|
|||
|
// 1) for same left point, the height would be descending order
|
|||
|
// 2) for same right point, the height would be ascending order
|
|||
|
int left, right, height;
|
|||
|
for(int i=0; i<buildings.size(); i++) {
|
|||
|
left = buildings[i][0];
|
|||
|
right = buildings[i][1];
|
|||
|
height = buildings[i][2];
|
|||
|
edges.push_back(make_pair(left, -height));
|
|||
|
edges.push_back(make_pair(right, height));
|
|||
|
}
|
|||
|
sort(edges.begin(), edges.end());
|
|||
|
|
|||
|
// 1) if we meet a left edge, then we add its height into a `set`.
|
|||
|
// the `set` whould sort the height automatically.
|
|||
|
// 2) if we meet a right edge, then we remove its height from the `set`
|
|||
|
//
|
|||
|
// So, we could get the current highest height from the `set`, if the
|
|||
|
// current height is different with preivous height, then we need add
|
|||
|
// it into the result.
|
|||
|
vector< pair<int, int> > result;
|
|||
|
multiset<int> m;
|
|||
|
m.insert(0);
|
|||
|
int pre = 0, cur = 0;
|
|||
|
for (int i=0; i<edges.size(); i++){
|
|||
|
pair<int,int> &e = edges[i];
|
|||
|
if (e.second < 0) {
|
|||
|
m.insert(-e.second);
|
|||
|
}else{
|
|||
|
m.erase(m.find(e.second));
|
|||
|
}
|
|||
|
cur = *m.rbegin();
|
|||
|
if (cur != pre) {
|
|||
|
result.push_back(make_pair(e.first, cur));
|
|||
|
pre = cur;
|
|||
|
}
|
|||
|
}
|
|||
|
return result;
|
|||
|
|
|||
|
}
|
|||
|
};
|