天际线问题

城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。现在,假设您获得了城市风光照片(图A)上显示的所有建筑物的位置和高度,请编写一个程序以输出由这些建筑物形成的天际线(图B)。

每个建筑物的几何信息用三元组 [Li,Ri,Hi] 表示,其中 Li 和 Ri 分别是第 i 座建筑物左右边缘的 x 坐标,Hi 是其高度。可以保证 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX 和 Ri - Li > 0。您可以假设所有建筑物都是在绝对平坦且高度为 0 的表面上的完美矩形。

例如,图A中所有建筑物的尺寸记录为:[ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ] 。

输出是以 [ [x1,y1], [x2, y2], [x3, y3], ... ] 格式的"关键点"(图B中的红点)的列表,它们唯一地定义了天际线。关键点是水平线段的左端点。请注意,最右侧建筑物的最后一个关键点仅用于标记天际线的终点,并始终为零高度。此外,任何两个相邻建筑物之间的地面都应被视为天际线轮廓的一部分。

例如,图B中的天际线应该表示为:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ]。

说明:

  • 任何输入列表中的建筑物数量保证在 [0, 10000] 范围内。
  • 输入列表已经按升序排列在左边的 x 位置 Li 。
  • 输出列表必须按 x 位排序。
  • 输出天际线中不得有连续的相同高度的水平线。例如 [...[2 3], [4 5], [7 5], [11 5], [12 7]...] 是不正确的答案;三条高度为 5 的线应该在最终输出中合并为一个:[...[2 3], [4 5], [12 7], ...]

思路

如果按照一个矩形一个矩形来处理将会非常麻烦,我们可以把这些矩形拆成两个点,一个左上顶点,一个右上顶点。将所有顶点按照横坐标排序后,我们开始遍历这些点。遍历时,通过一个堆来得知当前图形的最高位置。堆顶是所有顶点中最高的点,只要这个点没被移出堆,说明这个最高的矩形还没结束。对于左顶点,我们将其加入堆中。对于右顶点,我们找出堆中其相应的左顶点,然后移出这个左顶点,同时也意味这这个矩形的结束。具体代码中,为了在排序后的顶点列表中区分左右顶点,左顶点的值是正数,而右顶点值则存的是负数。

注意

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

复杂度

时间 O(NlogN) 空间 O(N)

 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>(11, new Comparator<Integer>(){
public int compare(Integer i1, Integer i2){
return i2 - i1;
}
});
// 将地平线值9先加入堆中
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;
}
}

Leetcode 218.天际线问题的更多相关文章

  1. Java实现 LeetCode 218 天际线问题

    218. 天际线问题 城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓.现在,假设您获得了城市风光照片(图A)上显示的所有建筑物的位置和高度,请编写一个程序以输出由这些建筑物形成的天际线 ...

  2. [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 ...

  3. LeetCode 218. The Skyline Problem 天际线问题(C++/Java)

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

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

  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. Swift LeetCode 目录 | Catalog

    请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift    说明:题目中含有$符号则为付费题目. 如 ...

  7. C#LeetCode刷题-分治算法

    分治算法篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...

  8. leetcode难题

    4 寻找两个有序数组的中位数       35.9% 困难     10 正则表达式匹配       24.6% 困难     23 合并K个排序链表       47.4% 困难     25 K ...

  9. C#LeetCode刷题-线段树

    线段树篇 # 题名 刷题 通过率 难度 218 天际线问题   32.7% 困难 307 区域和检索 - 数组可修改   42.3% 中等 315 计算右侧小于当前元素的个数   31.9% 困难 4 ...

随机推荐

  1. yii2 设置多个入口文件

    在web下希望加个core.php的后台入口,但因为权限问题,总是会跳转到index.php

  2. Sqlite数据库中索引的使用、索引的优缺点[转]

    原文链接1   原文链接2 3. 索引的种类 1)聚集索引:表中行的物理顺序与键值的逻辑(索引)顺序相同.因为数据的物理顺序只能有一种,所以一张表只能有一个聚集索引.如果一张表没有聚集索引,那么这张表 ...

  3. PHP使用Session遇到的一个Permission denied Notice解决办法

    搜索 session.save_path 在这里你有两个选择,一个是像我一样用; 把这一行注释掉,另一个选择就是修改一个 nobody 用户可以操作的目录,也就是说有读写权限的目录,我也查了下这个默认 ...

  4. JDK集合框架--ArrayList

    ArrayList,从类名就可以看出来,这是由数组实现的List,即内部是用数组保存元素的有序集合.先看看主要的成员变量,比较简单: public class ArrayList<E> e ...

  5. Html标签杂记

    <html> <head> <title> </title> </head> <body> </body> < ...

  6. Android动态权限申请

    Android系统中,目前Dangerous级别的权限都需要动态申请.步骤如下: 1.AndroidManfiest.xml中申明需要的动态权限 <?xml version="1.0& ...

  7. iOS-控件响应用户控制事件之事件处理

    事件处理 响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件.我们称之为“响应者对象” UIApplication.UIViewControlle ...

  8. 新萝卜家园Ghost版Win10系统X32极速装机版2015年4月

    来自:系统妈,系统下载地址:http://www.xitongma.com/windows10/2015-03-30/6638.html 新萝卜家园Ghost Win10 X32 10041电脑城极速 ...

  9. 迅为嵌入式4412平台兼容3G/4G模块的安卓开发板

    安卓开发板特点说明: 1. 配备16G固态硬盘EMMC存储 2. 64位双通道2GB内存 三星S5M8767电源管理 板载高精度GPS模块 CAN,RS-485等工业接口 板载WIFI蓝牙模块,陀螺仪 ...

  10. 新建 vue项目时报错,无法成功搭建项目

    之前电脑已经安装 Node环境和 vue-cli脚手架,但是过段时间没有使用,然后现在用 vue-cli 搭建项目的时候,启动服务器的时候报错,无法启动成功,摸索半天,发现是因为 Node和vue-c ...