218. The Skyline Problem

Difficulty:
Related Topics:
Similar Questions:

Problem

A city's skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Given the locations and heights of all the buildings, return **the *skyline* formed by these buildings collectively**.

The geometric information of each building is given in the array buildings where buildings[i] = [lefti, righti, heighti]:

You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.

The skyline should be represented as a list of "key points" sorted by their x-coordinate in the form [[x1,y1],[x2,y2],...]. Each key point is the left endpoint of some horizontal segment in the skyline except the last point in the list, which always has a y-coordinate 0 and is used to mark the skyline's termination where the rightmost building ends. Any ground between the leftmost and rightmost buildings should be part of the skyline's contour.

Note: There must be no consecutive horizontal lines of equal height in the output skyline. For instance, [...,[2 3],[4 5],[7 5],[11 5],[12 7],...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...,[2 3],[4 5],[12 7],...]

  Example 1:

Input: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]
Output: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]
Explanation:
Figure A shows the buildings of the input.
Figure B shows the skyline formed by those buildings. The red points in figure B represent the key points in the output list.

Example 2:

Input: buildings = [[0,2,3],[2,5,3]]
Output: [[0,3],[5,0]]

  Constraints:

Solution (Java)

class Solution {
    public List<List<Integer>> getSkyline(int[][] buildings) {
        List<List<Integer>> list = new ArrayList<>();
        List<int[]> lines = new ArrayList<>();
        for (int[] building : buildings) {
            lines.add(new int[] {building[0], building[2]});
            lines.add(new int[] {building[1], -building[2]});
        }
        lines.sort((a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);
        TreeMap<Integer, Integer> map = new TreeMap<>();
        map.put(0, 1);
        int prev = 0;
        for (int[] line : lines) {
            if (line[1] > 0) {
                map.put(line[1], map.getOrDefault(line[1], 0) + 1);
            } else {
                int f = map.get(-line[1]);
                if (f == 1) {
                    map.remove(-line[1]);
                } else {
                    map.put(-line[1], f - 1);
                }
            }
            int curr = map.lastKey();
            if (curr != prev) {
                list.add(Arrays.asList(line[0], curr));
                prev = curr;
            }
        }
        return list;
    }
}

Solution (Javascript)

/**
 * @param {number[][]} buildings
 * @return {number[][]}
 */
var getSkyline = function(buildings) {
    var res = [], height = [], pq = [0], prevMax = null;
    for(var b of buildings) {
        height.push([b[0], -b[2]]);
        height.push([b[1],  b[2]]);
    }
    height.sort((a, b) => {
        if(a[0] === b[0])  return a[1] - b[1];
        return a[0] - b[0];
    });

    for(var h of height) {
        if(h[1] < 0) {
            pq.push(-h[1]);
        } else {
            remove(pq, h[1]);
        }

        var maxV = Math.max(...pq);
        if(prevMax !== maxV) {  // maxV changed after remove h[1]
            res.push([h[0], maxV]);
            prevMax = maxV;
        }
    }
    return res;
};

var remove = function(arr, val) { // remove the first element equal to val
    var ind = -1;
    for(var i=0; i<arr.length; i++) {
        if(val === arr[i]) {
            ind = i;
            break;
        }
    }
    arr.splice(ind, 1);
    return;
};

Explain:

nope.

Complexity: