城市天際線道路升級,Leetcode 218.天際線問題

 2023-11-19 阅读 29 评论 0

摘要:天際線問題 城市的天際線是從遠處觀看該城市中所有建筑物形成的輪廓的外部輪廓。現在,假設您獲得了城市風光照片(圖A)上顯示的所有建筑物的位置和高度,請編寫一個程序以輸出由這些建筑物形成的天際線(圖B)。 每個建筑物的幾何信息用

天際線問題

城市的天際線是從遠處觀看該城市中所有建筑物形成的輪廓的外部輪廓。現在,假設您獲得了城市風光照片(圖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], ...]

思路

城市天際線2什么時候出、如果按照一個矩形一個矩形來處理將會非常麻煩,我們可以把這些矩形拆成兩個點,一個左上頂點,一個右上頂點。將所有頂點按照橫坐標排序后,我們開始遍歷這些點。遍歷時,通過一個堆來得知當前圖形的最高位置。堆頂是所有頂點中最高的點,只要這個點沒被移出堆,說明這個最高的矩形還沒結束。對于左頂點,我們將其加入堆中。對于右頂點,我們找出堆中其相應的左頂點,然后移出這個左頂點,同時也意味這這個矩形的結束。具體代碼中,為了在排序后的頂點列表中區分左右頂點,左頂點的值是正數,而右頂點值則存的是負數。

注意

  • 堆中先加入一個零點高度,幫助我們在只有最矮的建筑物時選擇最低值

復雜度

時間 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

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/179318.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息