Building Outline
Given N buildings in a x-axis,each building is a rectangle and can be represented by a triple (start, end, height),where start is the start position on x-axis, end is the end position on x-axis and height is the height of the building. Buildings may overlap if you see them from far away,find the outline of them。
An outline can be represented by a triple, (start, end, height), where start is the start position on x-axis of the outline, end is the end position on x-axis and height is the height of the outline.
Example:
Given 3 buildings:
[
[1, 3, 3],
[2, 4, 4],
[5, 6, 1]
]
The outlines are:
[
[1, 2, 3],
[2, 4, 4],
[5, 6, 1]
]
Solution:
Same problem like Number of Airplanes in the Sky. For a triple, we convert it to (index, height, isStart) format. (1, 3, 3) => (1, 3, true) and (3, 3, false). We put these new format of data in a PriorityQueue which sorts them based on index and then isStart. From the smallest index to the largest index, we could always push (index, height, isStart) into a max PriorityQueue which will give us the largest height at this moment as the outline. When one building is finished (isStart == false is triggered), we need to remove this height from the max PriorityQueue.
Code:
public class Solution {
/**
* @param buildings: A list of lists of integers
* @return: Find the outline of those buildings
*/
public ArrayList<ArrayList<Integer>> buildingOutline(int[][] buildings) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
if (buildings == null || buildings.length == 0 || buildings[0].length == 0) {
return res;
}
int m = buildings.length;
Queue<Event> eventQ = new PriorityQueue<Event>(m * 2);
for (int[] building : buildings) {
eventQ.offer(new Event(building[0], building[2], true));
eventQ.offer(new Event(building[1], building[2], false));
}
Queue<Integer> heightQ = new PriorityQueue<Integer>(m, Collections.reverseOrder());
int start = 0;
int lastH = 0;
while (!eventQ.isEmpty()) {
Event e = eventQ.poll();
if (e.isStart) {
heightQ.offer(e.val);
} else {
heightQ.remove(e.val);
}
int h = 0;
if (!heightQ.isEmpty()) {
h = heightQ.peek();
}
if (h != lastH) {
if (lastH > 0 && e.idx > start) {
ArrayList<Integer> temp = new ArrayList<>();
temp.add(start);
temp.add(e.idx);
temp.add(lastH);
res.add(temp);
}
start = e.idx;
lastH = h;
}
}
return res;
}
class Event implements Comparable<Event> {
int idx;
int val;
boolean isStart;
public Event(int index, int value, boolean start) {
idx = index;
val = value;
isStart = start;
}
@Override public int compareTo(Event that) {
if (this.idx != that.idx) {
return this.idx - that.idx;
}
if (this.isStart && !that.isStart) {
return -1;
} else if (!this.isStart && that.isStart) {
return 1;
} else {
return 0;
}
}
@Override public String toString() {
return idx + " " + val + " " + isStart;
}
}
}