Why Skyline Feels Difficult
It is tempting to begin with “Sweep Line plus Heap.” CCF begins with what must be proven: the answer, the evidence that can change it, the active scope, and what must survive movement.
Reasoning Stack: Answer Space → Problem Space → Decision Space → Transcription.
After deriving a lawful route, audit it for unnecessary state and work.
Problem Statement
Given buildings [left, right, height] sorted by left boundary, construct the visible outer contour as ordered skyline key points [x, height]. Emit a point only when the visible height changes.
buildings = [[2,9,10], [3,7,15], [5,12,12]]
x: 2 3 7 9 12
building: [----10-----]
[----15----]
[-------12-------]
skyline: [2,10] [3,15] [7,12] [12,0]
Answer Space
question: What must be returned, and what makes one result point lawful?
evidence: The requested result is a sequence of critical skyline changes, not building identities or every sampled coordinate.
reasoning: A point needs its horizontal location and visible height. Repeating an adjacent height adds no contour information.
answer: Answer Space: Array<[x, height]>, ordered by x, with only real height transitions and a final return to zero.
next: What input evidence can change that visible height?
The example emits [2,10], [3,15], [7,12], and [12,0]; it never emits duplicate height 15.
Problem Space
question: What evidence and relationship determine visibility?
evidence: Each building supplies left, right, and height. Buildings overlap, and input left boundaries are already ordered.
reasoning: At any x, the contour is the maximum height of buildings whose left is at or before x and whose right is after x. Only starts and ends can alter that maximum.
answer: Problem Space: an ordered Array<Building>; active overlap and the maximum active height are the decisive relationships.
next: What are we constructing from that evidence?
At x=3, heights 10 and 15 are active, so 15 is visible. At x=7, height 15 expires and height 12 becomes visible.
Decision Space
Intent
question: What semantic job does the problem require?
evidence: The verb is construct, the subject is the visible outer contour, and the result is a complete ordered sequence of key points.
reasoning: This is not merely finding a maximum at one coordinate. The result assembles every meaningful change into one lawful contour.
answer: Intent: Construction / Assembly.
next: What truth must remain true after every relevant coordinate?
Each emitted point extends a single contour; the final [12,0] closes it instead of returning an isolated maximum.
Invariant
question: What truth protects a correct constructed contour?
evidence: At each meaningful x, some started buildings remain relevant while others have expired.
reasoning: If the recorded height is not the maximum active height, the visible contour is wrong even if every building was visited.
answer: Invariant: after processing a relevant x, current skyline height equals the maximum height among buildings active at x.
next: What evidence is active in one frame?
After x=7, active height 12 is the maximum, so the prior visible height 15 must transition to 12.
Scope
question: What evidence is active in one Skyline frame?
evidence: The current frame has one x-coordinate and the buildings already active at that x.
reasoning: Expired buildings cannot affect the visible height. Future starts are not active evidence; they only help determine where a later frame begins.
answer: Scope: current x-coordinate plus currently active-building state, represented by height and right boundary.
next: What evidence determines the next meaningful frame?
At x=5, active buildings end at 7, 9, and 12. The next unconsumed left boundary is separate Next-Scope evidence, not part of Scope.
Scanner
question: Which coordinates are lawful Scanner destinations?
evidence: Next-Scope evidence is the next unconsumed building left boundary and the right boundary of the current tallest active building.
reasoning: Visibility changes only at those boundaries. Scanning every integer x repeats unchanged Scope, so the Scanner derives the next x from the two candidates.
answer: Scanner: Direct Sweep from one meaningful x to the next; no materialized 2n event list is required.
next: How does the current Scope become the next Scope?
From x=5, the next left is absent and tallest right is 7; advance directly to x=7 rather than testing x=6.
Next Scope
question: How does old Scope become next Scope?
evidence: At x=3, height 15 is active. The Scanner uses its right boundary 7 as Next-Scope evidence; height 12 remains active after that move.
reasoning: Scope defines active evidence now. Next-Scope evidence selects the next meaningful x. The Scanner then removes expired entries and adds starts to transform state.
answer: Move to the derived x, add all buildings starting there, then discard entries whose right boundary is at or before x.
next: Which active evidence must survive that movement?
Old Scope x=3 contains active heights 15 and 10. At next x=7, height 15 expires and the retained height 12 becomes visible.
Persistence Requirement
question: When Scope changes, what required information would be lost?
evidence: A building can start at x=5 but remain relevant after later Scanner frames at x=7 and x=9.
reasoning: The next frame cannot reconstruct earlier starts from its local coordinate alone. The invariant still needs their height and expiration boundary.
answer: Persistence Requirement: retain every started building until its right boundary is no longer beyond the current x.
next: Which structure supplies both persistence and repeated maximum queries?
The building [5,12,12] starts at x=5, survives x=7 and x=9, then expires at x=12.
Recorder
question: What smallest Recorder preserves that evidence?
evidence: Each frame needs insert by start, removal of expired top entries, and access to maximum active height.
reasoning: A max-priority queue keeps active candidates ordered by height. Lazy removal is lawful because an expired non-top candidate cannot affect the current maximum.
answer: Recorder: max heap / PriorityQueue of (right, height), prioritized by descending height.
next: When should the Answer Space receive a new key point?
At x=3 enqueue (7,15). It becomes the heap top; at x=7 lazy removal exposes the retained (12,12) entry.
Finalizer
question: What completes the constructed skyline?
evidence: The required output contains only changes in the visible maximum and ends after every active building expires.
reasoning: Compare the heap maximum with the last emitted height after each frame. Equality means no new contour point; a difference is the exact required transition.
answer: Finalizer: append [x, currentHeight] exactly when maximum active height differs from the prior emitted height.
next: What direct transcription is correct before the state-reduction audit?
At x=12 the heap becomes empty, current height becomes zero, and [12,0] is appended to close the skyline.
First Lawful Route
Baseline: Baseline route: create 2n boundary events, sort them, sweep left to right, and use a max heap.
Materializing two events per building, sorting by x, and maintaining active heights visits all relevant state changes without scanning coordinates.
The baseline event list has starts (2,10),(3,15),(5,12) and ends (7,15),(9,10),(12,12).
State-Reduction Audit
Rule: For every piece of state, ask whether the Invariant actually requires it to persist.
For every piece of state, ask whether the Invariant actually requires it to persist. The event list does not: both candidates for next x are already derivable.
Remove: explicit 2n event list. Keep: active-building Recorder.
REMOVE: 2n event list. KEEP: active-building heap. After left boundary 5, tallest right 7 supplies the next x without an event object.
Direct Sweep Derivation
The active-max-height invariant is unchanged; only the source of the next x is reduced.
Optimized Scope: input index, current x, and active max heap. Optimized Scanner: Direct Sweep over dynamically derived boundary coordinates.
Candidate next x values are 3 then 5 from input, then 7 from heap top; the sequence matches the event route without event allocation.
Optimized Recorder + Complexity
A priority queue stores precisely active buildings and makes maximum access immediate. Each item enters once and is removed once.
Recorder: Final Recorder: a max-priority queue keyed by height, storing right boundaries for lazy expiry.
O(n log n) time: O(n) heap insertions and removals with no event-list sorting pass. O(n) auxiliary space for active buildings in the priority queue.
The 12-Question Skyline Map
| # | Question | Derived answer |
| 1-3 | What must be returned? | Ordered [x,height] transitions |
| 4-6 | What evidence changes visibility? | Active-building maximum at boundaries |
| 7 | What is the Intent? | Construction / Assembly |
| 8 | What must remain true? | Current height is maximum active height |
| 9-10 | What is Scope and Scanner? | Direct Sweep through meaningful x values |
| 11 | What persists? | Started, unexpired buildings |
| 12 | What follows? | Max heap Recorder; emit changed height |
CCF-Compliant Python 3 Solution
from heapq import heappop, heappush
class Solution:
def getSkyline(self, buildings):
# Answer Space: ordered [x, height] key points.
result = []
# Problem Space: input is ordered by building left boundary.
active = []
index = 0
previous = 0
while index < len(buildings) or active:
# Scope: next input start and active buildings.
next_left = buildings[index][0] if index < len(buildings) else float('inf')
next_right = active[0][1] if active else float('inf')
# Scanner: Direct Sweep chooses the next meaningful x.
x = min(next_left, next_right)
while index < len(buildings) and buildings[index][0] == x:
left, right, height = buildings[index]
# Persistence Requirement: retain started buildings until expiry.
heappush(active, (-height, right))
index += 1
while active and active[0][1] <= x:
heappop(active)
# Invariant: this is the maximum active height at x.
height = -active[0][0] if active else 0
if height != previous:
# Finalizer: only visible height transitions enter the answer.
result.append([x, height])
previous = height
# Recorder: heapq keeps active buildings ordered by negative height.
# Efficiency Proof: next x is derived; no 2n event list is materialized.
return result
Complexity Analysis
Time: O(n log n) time: O(n) heap insertions and removals with no event-list sorting pass.
Auxiliary space: O(n) auxiliary space for active buildings in the priority queue.
Lazy cleanup can pop several expired entries in one frame, but every entry is popped once overall, so the total cleanup is O(n log n).
Why This Is Better Than Pattern Guessing
Pattern-first says: “This is Skyline. Use Sweep Line plus Heap.” CCF asks what changes the answer, what stays true, how Scope moves, and what must survive that movement. The Scanner and Recorder then emerge as consequences of evidence.
Algorithm names are conclusions, not starting assumptions.