## fantasia的博客

Somewhere on this planet

# Leetcode 218. The Skyline Problem 2016/10/5 UPDATE

### 218. The Skyline Problem

Total Accepted: 25930 Total Submissions: 105884 Difficulty: Hard

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

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.

1.可以新建一个数据结构或者直接使用int[]来保存

2.处理过后的数据的compare函数应该是如果坐标相同，那么后来的int[]应该排前面，也就是b[1]-a[1]。否则会出现多余的key point。

3.java默认是最小堆，所以需要自建最大堆并重写compare函数。

4.堆里面要先放入一个0。并且还要维护一个prev来代表之前的高度，这样在当前元素操作之后，可以对比peek()，如果不相等说明有新的key point产生。

public class Solution { // 250ms
public List<int[]> getSkyline(int[][] buildings) {
List<int[]> res = new ArrayList<int[]>();
List<int[]> data = new ArrayList<int[]>();
for(int i=0; i<buildings.length; i++){
}

Collections.sort(data, new Comparator<int[]>(){
public int compare(int[] a, int[] b){
if(a[0]!=b[0]) return a[0]-b[0];
else return b[1]-a[1]; // so that next block comes before cur block ends
}
}); // !!!!!!

PriorityQueue<Integer> max = new PriorityQueue<Integer>(15, new Comparator<Integer>(){
public int compare(Integer i1, Integer i2){
return i2-i1;
}
}); // !!!!!!

int prevH = 0;
for(int i=0; i<data.size(); i++){
int[] cur = data.get(i);
if(cur[1]<0) {
max.remove(-cur[1]);
}else{
}
int curH = max.peek();
if(curH!=prevH) {
prevH = curH;
}
}
return res;
}
}

10/5 UPDATE:

merge的过程是：判断俩building的起始位置：

1. l1的起始位置靠前，那么有可能加入的点的index被赋值为该位置，有可能加入的点的高度height = 之前height值和目前这个building的最大值。之后从l1中删除这个区间。

2. l2的起始位置靠前，那么有可能加入的点的index被赋值为该位置，有可能加入的点的高度height = 之前height值和目前这个building的最大值。之后从l2中删除这个区间。

3. 俩building的起始位置相同。那么就都取出来，比较高度，height被更新为这两者height1和height2的最大值。l1和l2都删除头元素。

Input:
[[0,2,3],[2,5,3]]
Expected:
[[0,3],[5,0]]

1. index = 0, height = 0。然后因为0 < 2，进入第一个if，height被更新为3，index为0，height1=3，然后l1 List中删除[0, 3]

2. index = 0, height = 0，头元素2=2，这样进入第三个block。index = 2， 然后俩List都删除头元素，height1 = 0， height2 = 3，height = max值3。也就是本次的待加入为[2, 3]。然后判断结果List不为空，并且结尾最后一个元素的height=3和当前待加入的元素相等，于是舍弃。

3. 这时一个LIST为空，跳出while循环，加入剩下的元素[5, 0]。

public class Solution { // 11ms
public List<int[]> getSkyline(int[][] buildings) {
if(buildings == null || buildings.length == 0)
return getSkyline(buildings, 0, buildings.length - 1);
}

private LinkedList<int[]> getSkyline(int[][] buildings, int lo, int hi) {
if(lo < hi) {
int mid = lo + (hi - lo) / 2;
return mergeSkylines(getSkyline(buildings, lo, mid), getSkyline(buildings, mid + 1, hi));
} else {                //  lo == hi, base case, add one building to skyline
return skyline;
}
}

int height1 = 0, height2 = 0;

while(skyline1.size() > 0 && skyline2.size() > 0) {
int index = 0, height = 0;
if(skyline1.getFirst()[0] < skyline2.getFirst()[0]) {
index = skyline1.getFirst()[0];
height1 = skyline1.getFirst()[1];
height = Math.max(height1, height2); // 左边的index小，说明height2仍然有效
skyline1.removeFirst();
} else if (skyline1.getFirst()[0] > skyline2.getFirst()[0]) {
index = skyline2.getFirst()[0];
height2 = skyline2.getFirst()[1];
height = Math.max(height1, height2); <span style="font-family: Arial, Helvetica, sans-serif;">//右边的index小，说明height1仍然有效</span>
skyline2.removeFirst();
} else {
index = skyline1.getFirst()[0];
height1 = skyline1.getFirst()[1];
height2 = skyline2.getFirst()[1];
height = Math.max(height1, height2); // 之前的height1 和 height2 都失效
skyline1.removeFirst();
skyline2.removeFirst();
}
if(skyline.size() == 0 || height != skyline.getLast()[1])
}

return skyline;
}
}

#### [leetcode] 218. The Skyline Problem 解题报告

2016-05-04 09:41:29

#### LeetCode 218. The Skyline Problem（天际线）

2016-05-06 07:03:27

#### [LeetCode]--218. The Skyline Problem

2016-08-14 21:15:11

#### leetcode 218. The Skyline Problem

2017-10-09 16:28:44

#### Leetcode 218. The Skyline Problem

2018-02-28 15:21:24

#### leetcode 218. The Skyline Problem java代码

2016-07-02 22:15:13

#### [LeetCode]218. The Skyline Problem

2017-02-24 18:48:21

#### 218. The Skyline Problem [leetcode]

2017-08-11 16:39:59

#### LeetCode 218. The Skyline Problem

2016-04-01 20:19:46

#### leetcode 218: The Skyline Problem

2015-06-03 18:10:47