The Skyline Problem

hard heap divide and conquer ordered set sweep line

Problem

Given a list of buildings as [left, right, height], return the skyline outline as a list of "key points" [x, y] in left-to-right order, where each key point is the left endpoint of a horizontal segment.

Inputbuildings = [[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]]
A corner is emitted only when the current maximum height in the heap changes.

import heapq

def get_skyline(buildings):
    events = []
    for l, r, h in buildings:
        events.append((l, -h, r))   # start
        events.append((r, 0, 0))    # end marker
    events.sort()
    res = []
    heap = [(0, float('inf'))]      # (-height, end)
    for x, negH, r in events:
        if negH != 0:
            heapq.heappush(heap, (negH, r))
        while heap[0][1] <= x:
            heapq.heappop(heap)
        cur = -heap[0][0]
        if not res or res[-1][1] != cur:
            res.append([x, cur])
    return res
function getSkyline(buildings) {
  const events = [];
  for (const [l, r, h] of buildings) {
    events.push([l, -h, r]);
    events.push([r, 0, 0]);
  }
  events.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
  const res = [];
  const heap = [[0, Infinity]]; // [-h, end] sorted as max-heap by -h
  const sortHeap = () => heap.sort((a, b) => a[0] - b[0]);
  for (const [x, negH, r] of events) {
    if (negH !== 0) { heap.push([negH, r]); sortHeap(); }
    while (heap[0][1] <= x) heap.shift();
    const cur = -heap[0][0];
    if (res.length === 0 || res[res.length - 1][1] !== cur) res.push([x, cur]);
  }
  return res;
}
class Solution {
    public List<List<Integer>> getSkyline(int[][] buildings) {
        List<int[]> events = new ArrayList<>();
        for (int[] b : buildings) {
            events.add(new int[]{b[0], -b[2], b[1]});
            events.add(new int[]{b[1], 0, 0});
        }
        events.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
        List<List<Integer>> res = new ArrayList<>();
        PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[0] - b[0]);
        heap.offer(new int[]{0, Integer.MAX_VALUE});
        for (int[] e : events) {
            if (e[1] != 0) heap.offer(new int[]{e[1], e[2]});
            while (heap.peek()[1] <= e[0]) heap.poll();
            int cur = -heap.peek()[0];
            if (res.isEmpty() || res.get(res.size()-1).get(1) != cur)
                res.add(Arrays.asList(e[0], cur));
        }
        return res;
    }
}
vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
    vector<array<int, 3>> events;
    for (auto& b : buildings) {
        events.push_back({b[0], -b[2], b[1]});
        events.push_back({b[1], 0, 0});
    }
    sort(events.begin(), events.end());
    vector<vector<int>> res;
    priority_queue<pair<int, int>> heap;  // (height, end)
    heap.push({0, INT_MAX});
    for (auto& e : events) {
        if (e[1] != 0) heap.push({-e[1], e[2]});
        while (heap.top().second <= e[0]) heap.pop();
        int cur = heap.top().first;
        if (res.empty() || res.back()[1] != cur) res.push_back({e[0], cur});
    }
    return res;
}
Time: O(n log n) Space: O(n)