天际线问题

城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。现在,假设您获得了城市风光照片(图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)

 1 public class Solution {
 2     public List<int[]> getSkyline(int[][] buildings) {
 3         List<int[]> result = new ArrayList<>();
 4         List<int[]> height = new ArrayList<>();
 5         // 拆解矩形,构建顶点的列表
 6         for(int[] b:buildings) {
 7             // 左顶点存为负数
 8             height.add(new int[]{b[0], -b[2]});
 9             // 右顶点存为正数
10             height.add(new int[]{b[1], b[2]});
11         }
12         // 根据横坐标对列表排序,相同横坐标的点纵坐标小的排在前面
13         Collections.sort(height, new Comparator<int[]>(){
14             public int compare(int[] a, int[] b){
15                 if(a[0] != b[0]){
16                     return a[0] - b[0];
17                 } else {
18                     return a[1] - b[1];
19                 }
20             }
21         });
22         // 构建堆,按照纵坐标来判断大小
23         Queue<Integer> pq = new PriorityQueue<Integer>(11, new Comparator<Integer>(){
24             public int compare(Integer i1, Integer i2){
25                 return i2 - i1;
26             }
27         });
28         // 将地平线值9先加入堆中
29         pq.offer(0);
30         // prev用于记录上次keypoint的高度
31         int prev = 0;
32         for(int[] h:height) {
33             // 将左顶点加入堆中
34             if(h[1] < 0) {
35                 pq.offer(-h[1]);
36             } else {
37                 // 将右顶点对应的左顶点移去
38                 pq.remove(h[1]);
39             }
40             int cur = pq.peek();
41             // 如果堆的新顶部和上个keypoint高度不一样,则加入一个新的keypoint
42             if(prev != cur) {
43                 result.add(new int[]{h[0], cur});
44                 prev = cur;
45             }
46         }
47         return result;
48     }
49 }

转载于:https://www.cnblogs.com/kexinxin/p/10203047.html

Leetcode 218.天际线问题相关推荐

  1. LeetCode——218. 天际线问题(The Skyline Problem)[困难]——分析及代码(Java)

    LeetCode--218. 天际线问题[The Skyline Problem][困难]--分析及代码[Java] 一.题目 二.分析及代码 1. 扫描线 + 优先队列 (1)思路 (2)代码 (3 ...

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

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

  3. LeetCode 218. 天际线问题(multiset优先队列)*

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

  4. LeetCode 218. 天际线问题(C++)*

    思路:优先队列+遍历 1.对于左端点:左端点且高度最高的那个就是左边缘: 2.对于右端点:首先右端点不可能是右边界;如果被删除的右端点是最高的,只有删除最高右端点后,该横坐标处的最高点才会是右边界: ...

  5. leetcode 218. 天际线问题

    城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓.给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 . 每个建筑物的几何信息由数组 buildings 表示,其中三元组 bu ...

  6. LeetCode | 218. 天际线问题

    城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓.给你所有建筑物的位置和高度,请返回由这些建筑物形成的天际线 . 每个建筑物的几何信息由数组 buildings 表示,其中三元组 bui ...

  7. LeetCode动画 | 218.天际线问题

    今天分享一个LeetCode题,题号是218,标题是天际线问题,题目标签是线段树和Line Sweep [ 扫描线算法 ] ,题目难度是困难.最近新学了Go语言,来尝试一下效果,同时后面也贴出了Jav ...

  8. leetcode:218. 天际线问题【区间修改 + 单点查询 + 找最大值板子 + 线段树】

    分析 用哈希+set压缩一下 最终只考虑楼的不重复端点即可 最后返回每个端点处的最大值 ac code from functools import reduceclass SegTree:'''通用线 ...

  9. leetcode 218. The Skyline Problem | 218. 天际线问题(线段树)

    题目 https://leetcode-cn.com/problems/the-skyline-problem/ 题解 线段树问题,根据左神的思路改编,外加我想到的压缩的 tricks(数字范围太大, ...

最新文章

  1. MySQL基础篇:数据类型
  2. SQL Server 2008 R2 安全性专题(一):安全原则
  3. VB访问SQL Server数据库技术全揭密
  4. SAP云平台上的SSO Principal Propagation设置
  5. Spark的ShuffleManager
  6. html 说明文档样式,通用模板说明文档
  7. 第一次正面交火!版主说博文里有广告!
  8. 语音识别入门:从菜鸟到大佬
  9. android之canvas绘制矩形
  10. 又是一个秋天~~~~
  11. Android Framework内核之旅
  12. 常用排序算法(三)直接插入排序
  13. mysql中的utf-8_永远不要在MySQL中使用UTF-8
  14. 使用Gradle编译Java项目
  15. android 系统的切图方式_Android UI设计及切图
  16. DFT频谱泄漏的数学分析及不产生泄漏的条件
  17. 什么是浏览器?2、常见的主流浏览器及其内核?什么是服务器?(学习笔记)
  18. 实战案例:抽屉自动点赞与爬取汽车之家新闻
  19. U盘显示文件或目录损坏且无法读取(U盘提示无法访问解决方法)
  20. 3Com收购华为2%持股 有望控股双方合资公司

热门文章

  1. Vue.js中this.$nextTick()的使用
  2. 题目 1885: 2017 分巧克力
  3. pjk static tp.php,在测试服上偶然出现 Error: Loading chunk 5 failed.
  4. textarea文本框默认显示文本鼠标点击时清空
  5. intellij IDEA 报 非法字符 \65279 原因及解决方法
  6. 纯html网页,如何快速把所有字体的颜色都改成黑色的,原来模板默认的字体是灰色
  7. Java实现Excel中的NORMSDIST函数和NORMSINV函数
  8. Firefox的缓存问题
  9. 【软考】2021软件设计师复习开坑指南
  10. 机器学习中用到的概率知识_机器学习导论(附录)–概率论知识