Search lands in PR-5.1 (Pagefind).

How-to Advanced

Chapter 1 Updated

The Skyline Problem

Sweep events left-to-right; emit a key point whenever the active max height changes.

  • Full 7m
  • Revision
  • Flow

Problem Statement

Given a list of buildings where each entry is [left, right, height], return the skyline silhouette as a list of “key points” [x, height] that describe the outline when viewed from afar.

Input

An array of buildings, each a [left, right, height] triple.

Example input
[[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]]

Output

The list of key points forming the silhouette, in ascending x. The final key point drops to height 0.

Expected output
[[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]

Constraints

  • 1 ≤ buildings.length ≤ 10⁴
  • 0 ≤ leftᵢ < rightᵢ ≤ 2³¹ − 1
  • 1 ≤ heightᵢ ≤ 2³¹ − 1
  • buildings is sorted by leftᵢ ascending.

Intuition

Sweep line + max-heap of active heights. For each building produce two events: a start (left, −height, right) and an end marker (right, 0, 0). Sort events by x. While sweeping:

  1. On a start event, push the building into the active heap.
  2. Lazily evict heap entries whose right-edge is ≤ current x.
  3. The heap top is the current skyline height. If it differs from the previously emitted height → emit [x, height] as a key point.
Sweep mechanics
Active max height changes only at two moments:
  (a) a new building enters taller than current max → emit [x, new_max]
  (b) the current max building exits → emit [x, new_max_after_eviction]
 
Between those moments the silhouette is flat; no new key point needed.

Solution

skyline.py
import heapq
 
def getSkyline(buildings: list[list[int]]) -> list[list[int]]:
    events = []
    for l, r, h in buildings:
        events.append((l, -h, r))   # start — negative height for max-heap via min-heap
        events.append((r, 0, 0))    # end marker
    events.sort()
 
    result = [[0, 0]]
    active = [(0, float('inf'))]    # (neg_height, right_edge)
 
    for x, neg_h, r in events:
        if neg_h:
            heapq.heappush(active, (neg_h, r))
        # Lazy eviction of buildings whose right edge has passed
        while active[0][1] <= x:
            heapq.heappop(active)
        max_h = -active[0][0]
        if max_h != result[-1][1]:
            result.append([x, max_h])
 
    return result[1:]

Complexity

MetricValueReason
TimeO(n log n)Sorting events + heap ops with lazy deletion
SpaceO(n)Events + active heap scale with building count

Edge Case Thinking

ScenarioHandling
Single buildingTwo key points: [left, h] and [right, 0].
Buildings share an edge (l, _, h) & (l, _, h')Sort tie-breaker on -h first keeps the taller emission correct.
Fully contained buildingNever affects the outline; heap evicts it silently.
Tall sliver inside a wide short buildingEmits a spike — [x, tall] and then drops back when the sliver exits.
Consecutive equal heightsSkyline does not emit a new key point — the equality check at the end suppresses it.

Comments

Comments are disabled in this environment. Set PUBLIC_GISCUS_REPO, PUBLIC_GISCUS_REPO_ID, and PUBLIC_GISCUS_CATEGORY_ID to enable.