LeetCode 218. The Skyline Problem
原题链接在这里:https://leetcode.com/problems/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).
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], ...]
题解:
发现result里的点都是高度出现落差时出现的。
把input 拆成左节点横坐标与高,右节点很坐标与高,为了区分,右节点的高设成负值。都插入verti List里然后排序。排序的Comparator 是先按照横坐标从小到大排序,若是横坐标相同,按照高度从大到下排序,因为若是两个building相连,第二个比第一个高, res只保存一个点就是高building的左上角.
从前往后扫verti, 遇到左边就把其高度存入大堆里,更新cur为最大高,遇到右边就把对应左边拿出,更新cur = maxHeap.isEmpty() ? 0 : maxHeap.peek().
当前最大高度cur 与之前最大高度 pre不同时,就吧{temp[0], cur} 存入res中去.
Time Complexity: O(nlogn). n = buildings.length.
Space: O(n).
AC Java:
1 public class Solution { 2 public List<int[]> getSkyline(int[][] buildings) { 3 List<int []> res = new ArrayList<int []>(); 4 if(buildings == null || buildings.length == 0 || buildings[0].length != 3){ 5 return res; 6 } 7 8 PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(Collections.reverseOrder()); 9 List<int []> verti = new ArrayList<int []>(); 10 for(int [] build : buildings){ 11 verti.add(new int[]{build[0], build[2]}); //左边界 12 verti.add(new int[]{build[1], -build[2]}); //右边界,高度存成负数以便区分 13 } 14 Collections.sort(verti, new Comparator<int []>(){ 15 public int compare(int [] a1, int[] a2){ 16 if(a1[0] == a2[0]){ 17 return a2[1] - a1[1]; 18 } 19 return a1[0] - a2[0]; 20 } 21 }); 22 23 int pre = 0; //之前最大高度 24 int cur = 0; //当前最大高度 25 for(int [] build : verti){ 26 if(build[1] > 0){ //左边界 27 maxHeap.add(build[1]); 28 cur = maxHeap.peek(); 29 }else{ //右边界 30 maxHeap.remove(-build[1]); 31 cur = maxHeap.isEmpty() ? 0 : maxHeap.peek(); 32 } 33 34 if(cur != pre){ //出现高度差 35 res.add(new int[]{build[0], cur}); 36 pre = cur; 37 } 38 } 39 return res; 40 } 41 }