2015-10-18 10:42:52 +08:00

141 lines
7.3 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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;
}
};