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.

Notice

Please merge the adjacent outlines if they have the same height and make sure different outlines cant overlap on x-axis.

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]
]
class Node {
    int pos;
    int height;
    boolean isStart;
    public Node(int pos, int height, boolean isStart) {
        this.pos = pos;
        this.height = height;
        this.isStart = isStart;
    }
}
class NodeComparator implements Comparator<Node> {
    @Override
    public int compare(Node n1, Node n2) {
        if(n1.pos != n2.pos) {
            return n1.pos - n2.pos;
        }
        else if(n1.isStart && n2.isStart) {
            return n2.height - n1.height;
        }
        else if(!n1.isStart && !n2.isStart) {
            return n1.height - n2.height;
        }
        else {
            return n1.isStart ? -1 : 1;
        }
    }
}
public ArrayList<ArrayList<Integer>> buildingOutline(int[][] buildings) {
    ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
    if (buildings == null || buildings.length == 0 || buildings[0].length == 0) {
        return res;
    }
    int m = buildings.length, col = buildings[0].length;
    List<Node> edges = new ArrayList<Node>();
    for (int i = 0; i < buildings.length; i++) {
        edges.add(new Node(buildings[i][0], buildings[i][2], true));
        edges.add(new Node(buildings[i][1], buildings[i][2], false));
    }
    Collections.sort(edges, new NodeComparator());
    PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(m * col, Collections.reverseOrder());
    for (Node n : edges) {
        if(n.isStart) {
            if(maxHeap.isEmpty() || n.height > maxHeap.peek()) {
                ArrayList<Integer> item = new ArrayList<Integer>();
                item.add(n.pos);
                item.add(n.height);
                res.add(item);
            }
            maxHeap.offer(n.height);
        }
        else {
            maxHeap.remove(n.height);
            if (!maxHeap.isEmpty() && maxHeap.peek() < n.height) {
                ArrayList<Integer> item = new ArrayList<Integer>();
                item.add(n.pos);
                item.add(maxHeap.peek());
                res.add(item);
            }
            else if (maxHeap.isEmpty()) {
                ArrayList<Integer> item = new ArrayList<Integer>();
                item.add(n.pos);
                item.add(0);
                res.add(item);
            }
        }
    }
    return getResult(res);
}
public ArrayList<ArrayList<Integer>> getResult(ArrayList<ArrayList<Integer>> res) {
    if(res.size() == 0) {
        return res;
    }
    ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
    int start = res.get(0).get(0);
    int height = res.get(0).get(1);
    for(int i = 1; i < res.size(); i++) {
        int end = res.get(i).get(0);
        if(height > 0) {
            ArrayList<Integer> item = new ArrayList<Integer>();
            item.add(start);
            item.add(end);
            item.add(height);
            ans.add(item);
        }
        start = end;
        height = res.get(i).get(1);
    }
    return ans;
}

results matching ""

    No results matching ""