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).

 

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_MAX0 < 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] ].

分析:一个城市在远处的轮廓是由该城市中所有建筑的轮廓覆盖在一起所形成的,现在假设给出你所有建筑的位置和高度(如图A),用程序输出有这些建筑集合所形成的轮廓(如图B)。

每座建筑物的几何信息由一组整数[Li, Ri, Hi]表示,Li, Ri分别表示建筑物x轴方向上左,右的坐标位置,Hi代表建筑物的高度。已经确定0 ≤ Li, Ri ≤ INT_MAX0 < Hi ≤ INT_MAX 且 Ri - Li > 0。你可以假设所有的建筑物都是完美的矩形且建造在绝对平滑的表面即高度为0的表面。

例如,图A中建筑物的尺寸为[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] .

输出是一个“关键点”的列表(如图B的红点)以格式[ [x1,y1], [x2, y2], [x3, y3], ... ]唯一确定一个轮廓。一个关键点以一条水平线段的左端点表示。注意,最后的关键点,在最右建筑的末尾,仅仅标志着轮廓的结束,该点的高度总是为0。此外,在两个相邻建筑物之间的地面也应该被考虑为轮廓的一部分。

一个简便的思路是,根据横坐标排序,然后遍历求拐点。求拐点的时候用一个最大化heap来保存当前的楼顶高度,遇到左边节点,就在heap中插入高度信息,遇到右边节点就 从heap中删除高度。分别用pre与cur来表示之前的高度与当前的高度,当cur != pre的时候说明出现了拐点。

package _218_The_Skyline_Problem;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

public class Solution {
    public List<int[]> getSkyline(int[][] buildings) {
		List<int[]> result = new ArrayList<int[]>();
		//默认初始堆大小11
    	PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11, new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				// TODO Auto-generated method stub
				return o2 - o1;
			}
    		
		});
    	//保存即将排序后的轮廓边缘点
    	List<int[]> sort = new ArrayList<int[]>();
    	
    	for(int i = 0; i < buildings.length; i++) {
    		int[] building = buildings[i];
    		sort.add(new int[]{building[0], building[2]});
    		sort.add(new int[]{building[1], -building[2]});
    	}
    	//将所有轮廓边缘点排序
    	Collections.sort(sort, new Comparator<int[]>() {

			@Override
			public int compare(int[] o1, int[] o2) {
				// TODO Auto-generated method stub
				if(o1[0] != o2[0])
					return o1[0] - o2[0];
				else
					return o2[1] - o1[1];
			}
		});
    	
    	int pre = 0;
    	int cur = 0;
    	for(int i = 0; i < sort.size(); i++) {
    		int[] building = sort.get(i);
    		if(building[1] > 0) {
    			maxHeap.add(building[1]);
    			cur = maxHeap.peek();
    		} else {
    			maxHeap.remove(-building[1]);
    			cur = (maxHeap.peek() == null) ? 0:maxHeap.peek();
    		}
    		//当前结点与前一结点不同,说明遇到拐点
    		if(cur != pre) {
    			result.add(new int[]{building[0], cur});
    			pre = cur;
    		}
    	}
    	
    	return result;
        
    }
}


你可能感兴趣的:(LeetCode)