[LeetCode][Java]The Skyline Problem
2015-11-18 16:10
435 查看
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).![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/31/420ffb8665ea7d822aa8bb85bc5cd42e.jpg)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/31/2785bc0466c1fe3d6e455820cef65638.jpg)
The geometric information of each building is represented by a triplet of integers
[Li, Ri, Hi], where
Liand
Riare the x coordinates of the left and right edge of the ith building, respectively, and
Hiis 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], ...]
https://leetcode.com/problems/the-skyline-problem/
先简化问题,其实就是求大楼轮廓的拐点。
如果用暴力求解,可以开一个大楼高度的数组,记录横坐标每一点上最高的高度,根据高度的最大值可以直接求出结果。
暴力坐标过大的情况下出错,本题最大的坐标是MAX_INT,开不出这么大的数组:
public static List<int[]> getSkyline_RuntimeError(int[][] buildings) { int[] height = new int[10000]; List<int[]> result = new ArrayList<int[]>(); int max = 0; for(int i = 0; i < buildings.length; i++){ int leftX = buildings[i][0], rightX = buildings[i][1], h = buildings[i][2]; for(int j = leftX; j <= rightX; j++){ height[j] = Math.max(height[j], h); } max = Math.max(max, rightX); } for(int i = 1; i < max; i++){ if(height[i] > height[i - 1]){ int[] tmp = new int[]{i, height[i]}; result.add(tmp); } else if(height[i] < height[i - 1]){ int[] tmp = new int[]{i - 1, height[i]}; result.add(tmp); } } if(max != 0){ int[] tmp = new int[]{max, 0}; result.add(tmp); } return result; }
换一种思路,用一个大根堆维护最高的高度,增加或删除一幢大楼时,维护高度Heap。
结果只跟大楼顶边有关,只需把这条边的两个顶点加入list中,还要标示出是start还是end。
start的点加入到堆中,end从堆中移出。
list的顺序直接影响到结果,排序依照:
1. x坐标从小到大
2. start在前,end在后 (顶边重合的case --> input : {{0,2,3},{2,5,3}}, output : [[0,3],[5,0]])
3. 1和2都相同时,start节点的y从大到小,end节点的y从小到大 (左右边重合的case --> input : {{1,2,1},{1,2,2},{1,2,3}}, output : [[1,3],[2,0]])
排序后遍历,与上次最高高度不同的点就是拐点。
https://leetcode.com/discuss/67995/accepted-solution-maxheap-interval-overlapping-explained
AC代码:
public class Solution { public static List<int[]> getSkyline(int[][] buildings) { class Node{ private int x, y; private boolean isStart; Node(int x, int y, boolean isStart){ this.x = x; this.y = y; this.isStart = isStart; } } List<int[]> result = new ArrayList<int[]>(); Queue<Integer> heap = new PriorityQueue<Integer>(Collections.reverseOrder()); heap.add(0); List<Node> arr = new ArrayList<Node>(); for(int i = 0; i < buildings.length; i++){ arr.add(new Node(buildings[i][0], buildings[i][2], true)); arr.add(new Node(buildings[i][1], buildings[i][2], false)); } Collections.sort(arr, new Comparator<Node>(){ public int compare(Node a, Node b) { if(a.x != b.x){ return a.x - b.x; }else if(a.isStart != b.isStart){ return a.isStart ? -1 : 1; }else{ if(a.isStart){ return b.y - a.y; }else{ return a.y - b.y; } } } }); int previousHeight = -1; for(int i = 0; i < arr.size(); i++){ Node curr = arr.get(i); if(curr.isStart){ heap.add(curr.y); }else{ heap.remove(curr.y); } int maxHeight = heap.peek(); if(curr.y >= maxHeight && previousHeight != maxHeight){ result.add(new int[]{curr.x, maxHeight}); } previousHeight = maxHeight; } return result; } }
相关文章推荐
- CS378: Autonomous Intelligent Robotics (FRI) -- Spring 2013
- java 字节流和字符流的区别
- 用标准版的Eclipse搭建PHP环境
- spring获取数组参数(二)
- Java编程实现中英混合字符串数组按首字母排序的方法
- 导入java项目到eclipse中中文乱码的解决办法
- java类加载过程
- Maven Tips
- spring aop
- Java访问权限
- JAVA中String常量存储在哪
- 简单的Java程序 简约不简单
- Java中获取文件大小的正确方法
- struts学习
- Plexus——Spring之外的IoC容器
- Spring - Spring容器概念及其初始化过程
- Spring - Spring容器概念及其初始化过程
- ios下使用RSA算法加密与java后台解密配合demo
- java代码获取系统时间和执行定时任务
- Java判断输入的String是否为中文方法总结