https://leetcode.com/problems/the-skyline-problem/description/

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

思路

比较经典的一题,题目太长完全不需要全部看,直接看两张图以及输入输出就知道题目要干啥了。

看了解析https://briangordon.github.io/2014/08/the-skyline-problem.html,从矩形的左右边入手,将左边和右边在x轴上的点作为critical point,然后:

for each critical point c
c.y gets the height of the tallest rectangle over c

要做的是确定cirtical point的高度。在遍历这些critical point时,通过一个堆来得知 over current critical point c的所有矩形的最高高度,更新critical point的高度。堆顶是最高的点,如果没被移出则表明这个最高的矩形还没结束。对于矩形的左顶点,将其加入堆中,对于右顶点,找出堆中其相应的左顶点并移除它,也就是说在我们从左往右遍历critical point时这个矩形已经结束了。具体代码中,为了在排序后的顶点列表中区分左右顶点,左顶点的值是负数,而右顶点值则存的是正数。

堆中先加入一个零点高度,帮助我们在只有最矮的建筑物时选择最低值。

int[][] buildings, 矩形被存储了一个二维数组,每一行是一个矩形,有3个值,分别是矩形的底在x轴上的左边的点和右边的点,以及矩形的高度,比如[2 9 10]
int[] height, 用于记录critical point所在边的高度,只有两个值,分别是x轴坐标和高度,比如height[0]=1,height[1]=4,表示在x轴为1处的边其高为4
public class Solution {
public List<int[]> getSkyline(int[][] buildings) {
List<int[]> result = new ArrayList<>();
List<int[]> height = new ArrayList<>();
// 拆解矩形,构建顶点的列表
for(int[] b:buildings) {
// 左顶点存为负数
height.add(new int[]{b[0], -b[2]});
// 右顶点存为正数
height.add(new int[]{b[1], b[2]});
}
// 根据横坐标对列表排序,相同横坐标的点纵坐标小的排在前面
Collections.sort(height, new Comparator<int[]>(){
public int compare(int[] a, int[] b){
if(a[0] != b[0]){
return a[0] - b[0];
} else {
return a[1] - b[1];
}
}
});
// 构建堆,按照纵坐标来判断大小
Queue<Integer> pq = new PriorityQueue<Integer>(new Comparator<Integer>(){
public int compare(Integer i1, Integer i2){
return i2 - i1;
}
});
// 将地平线值0先加入堆中
pq.offer(0);
// prev用于记录上次keypoint的高度
int prev = 0;
for(int[] h:height) {
// 将左顶点加入堆中
if(h[1] < 0) {
pq.offer(-h[1]);
} else {
// 将右顶点对应的左顶点移去
pq.remove(h[1]);
}
int cur = pq.peek();
// 如果堆的新顶部和上个keypoint高度不一样,则加入一个新的keypoint
if(prev != cur) {
result.add(new int[]{h[0], cur});
prev = cur;
}
}
return result;
}
}

参考:https://segmentfault.com/a/1190000003786782

注意上面比较器和用PriorityQueue来实现堆数据结构,比较器在java 1.8中还可以通过Lambda表达式来实现,简洁很多。

LeetCode218. The Skyline Problem的更多相关文章

  1. [Swift]LeetCode218. 天际线问题 | The Skyline Problem

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  2. [LeetCode] The Skyline Problem 天际线问题

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  3. [LeetCode] The Skyline Problem

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  4. The Skyline Problem

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  5. [LeetCode#218] The Skyline Problem

    Problem: A city's skyline is the outer contour of the silhouette formed by all the buildings in that ...

  6. [LeetCode] 281. The Skyline Problem 天际线问题

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  7. [LeetCode] 218. The Skyline Problem 天际线问题

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  8. Java for LeetCode 218 The Skyline Problem【HARD】

    A city's skyline is the outer contour of the silhouette formed by all the buildings in that city whe ...

  9. UVa 105 - The Skyline Problem(利用判断,在于想法)

    题目来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&pa ...

随机推荐

  1. 51nod 1273 旅行计划(思维题)

    一开始看到这题真的有点懵逼...一直在想着套算法,结果题解除了sort和dfs其他什么都没用到 显然每次到达的一定都是叶子,先从根节点dfs一遍,按深度对叶子降序排序,按这个顺序向根节点dfs,路径上 ...

  2. Nginx的配置文件简介及在Nginx中配置基于不同ip的虚拟主机

    Nginx的配置文件简介及在Nginx中配置基于不同ip的虚拟主机: #user nobody; worker_processes 1; #error_log logs/error.log; #err ...

  3. JNA的用法

    JNA(Java Native Access):建立在JNI之上的Java开源框架,SUN主导开发,用来调用C.C++代码,尤其是底层库文件(windows中叫dll文件,linux下是so[shar ...

  4. JavaScript中进制之间的转换

    JavaScript中进制之间的转换 //十进制转其他 var x = 100; alert(x); alert(x.toString(2)); //转2进制 alert(x.toString(8)) ...

  5. some interesting words

    No one gets rich betting against the market. Never bet against the Fed. Bulls make money, bears make ...

  6. Intervals ZOJ - 3953 (区间贪心)

    Chiaki has n intervals and the i-th of them is [li, ri]. She wants to delete some intervals so that ...

  7. python练习:抓取统计log内ip数量

    #!/usr/bin/python #-*- coding: utf- -*- import os import re rawfile = '/var/log/auth.log' def rawpar ...

  8. python递归读取目录列表

    import os def listdirs(base): for line in os.listdir(base): fullpath = os.path.join(base,line) if os ...

  9. 查看Django版本

    python -m django --version dd

  10. rwx

    常用的linux文件权限:444 r--r--r--600 rw-------644 rw-r--r--666 rw-rw-rw-700 rwx------744 rwxr--r--755 rwxr- ...