LeetCode218. 天際線問題
阿新 • • 發佈:2019-01-09
題解
如果按照一個矩形一個矩形處理會非常麻煩,我們把這些矩形拆成兩個點,一個左上角頂點,一個右上角頂點。將所有頂點按照橫座標進行排序然後開始遍歷,遍歷時通過一個堆來得知當前圖形的最高位置,堆頂是所有頂點中最高的點,只要這個點沒被移出堆,就說明這個最高的矩形還沒結束。對於左頂點,我們將其加入堆中,對於右頂點,我們找出堆中相應的最頂點,然後移出左頂點,同時也意味著這個矩形的結束,為了區分左右頂點,我們以負數作為左頂點,正數作為右頂點
程式碼
public class Solution {
public static List<int[]> getSkyline(int[][ ] buildings) {
List<int[]> res = 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];
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;
}
});
pq.add(0);// 首先加入地平線起始點0
int prev = 0;// prev用於記錄上次keyPoint的高度
for (int[] h : height) {
if (h[1] < 0)// 左頂點加入堆
pq.add(-h[1]);
else
pq.remove(h[1]);// 將右頂點對應的左頂點移出
int cur = pq.peek();
if (prev != cur) {// 如果堆的新頂部和上個keypoint高度不一樣,則加入一個新的keypoint
res.add(new int[] { h[0], cur });
prev = cur;
}
}
return res;
}
}