Hi👋SpeedAlgo • Deliberate Practice & Cognitive Ergonomics for Software Engineers

An interactive algorithm mastery and technical interview preparation platform published by Hi👋WebEnterprise. Built for senior and staff software engineers preparing for rigorous coding screens at top tech companies (FAANG/MAMAA).

13 Core Algorithmic Patterns & 225 Practice Problems

  • 1. Two Pointers (16 Paradigms, 43 Problems): Opposite ends, sorted pair sums, palindrome verification, trapping rain water, 3Sum, container with most water — includes the Sliding Window and Fast & Slow Pointers paradigms (contiguous subarray invariants, longest substrings, Floyd's cycle detection, linked list middle).
  • 2. Binary Search (9 Paradigms, 14 Problems): Monotonic predicate partitioning (feasible(x)), boundary search, rotated sorted arrays, square roots, minimum ship capacity, median of two sorted arrays, matrix median on value range.
  • 3. Bit Manipulation (5 Paradigms, 11 Problems): Counting set bits, XOR cancellation, bit reversal, bitmask pairing, maximum XOR with a bitwise trie.
  • 4. Math & Geometry (8 Paradigms, 14 Problems): Sieve of Eratosthenes, integer/roman conversions, modular arithmetic, geometric simulation.
  • 5. Tree/Graph Depth-First Search (15 Paradigms, 24 Problems): Path sums, lowest common ancestor, tree diameter, validating BSTs, tree DP (House Robber III, Binary Tree Cameras).
  • 6. Tree/Graph Breadth-First Search (5 Paradigms, 12 Problems): Level-order traversals, shortest path in unweighted graphs, zig-zag traversals, rotting oranges, word ladders.
  • 7. Graphs (12 Paradigms, 22 Problems): Topological sort, cycle detection, Dijkstra's algorithm, bipartite graph validation, network delay.
  • 8. Backtracking (6 Paradigms, 14 Problems): Subsets, permutations, combinations, constraint satisfaction, pruning, N-Queens, Sudoku solver.
  • 9. Dynamic Programming (13 Paradigms, 28 Problems): Memoization vs tabulation, 0/1 knapsack, unbounded knapsack, coin change, edit distance, longest common subsequence.
  • 10. Heap / Priority Queue (9 Paradigms, 11 Problems): Running medians, top-k elements, interval scheduling, IPO, k-way merges.
  • 11. Advanced Data Structures (7 Paradigms, 17 Problems): Trie (prefix tree), Union-Find (Disjoint Set Union), LRU Cache, LFU Cache, range-sum queries with updates.
  • 12. Stack (5 Paradigms, 9 Problems): Next greater element, largest rectangle in histogram, remove k digits, decode string, min stack.
  • 13. Intervals & Greedy (2 Paradigms, 6 Problems): Merge intervals, interval scheduling, meeting rooms by sweep line, jump game.

4-Stage Deliberate Practice Framework

  1. Stage 1 (Compare & Learn): Read the pattern's mental model, loop invariant and Big-O proof, compare the pattern's template with the problem's solution side by side, and use the step-by-step debugger. The solution can also be shown in C#, Java, TypeScript, C++, Go or Rust for almost every problem.
  2. Stage 2 (Active Recall): Rebuild the solution from memory in a code editor, with an invariant checklist and optional progressive hints, and check it against a judged test suite.
  3. Stage 3 (AI Interview Coach, coming soon): A mock-interview stage still in development; for now, students go straight from Stage 2 to Stage 4.
  4. Stage 4 (Solve on Your Own): Solve a new problem on your own against a 15-minute timer; your code is graded against a test suite. Python and TypeScript run in your browser and C# runs on our server (design problems grade in Python and TypeScript).

Equipped with a spaced-repetition review hub on a fixed 7-step schedule (1 day up to 90 days), a two-pane Studio workspace, and study notes.

Pricing, Access & Commercial Terms

  • Core Curriculum: 100% Free. No credit card required.
  • Coins: New accounts get 40 free coins once, the daily claim adds +20 coins once a day, and inviting a friend earns you +25 coins when they complete their first practice step. These are the only ways to earn coins.
  • AI Coach: Each AI coach question costs 1-5 coins, priced by the server according to its size.
  • BYOK (Bring Your Own Key): AI coaching is free with your own Google Gemini, OpenAI or OpenRouter API key (BYOK).
  • Extras: Coins also unlock extras for 24 hours: a Recall hint level (1 coin), a Solve solution reveal (2), a LeetCode problem card's solutions (1) and a pattern's extra canonical problems (1).
  • Payments & Refunds: Nothing on the site is sold for money: coins can only be earned, never bought. There are no subscriptions or charges, so there is nothing to refund.
  • Platform Operator: Hi👋WebEnterprise. Support & policies at hispeedalgo.com.
Skip to main content
Hi👋SpeedAlgo

Invariant-First Algorithmic Mastery

Arena
238Items
Theory Context•Intervals & Greedy

Builds on Merge Intervals, which you haven’t finished yet.

P1MediumBuilt on Merge Intervals~4 min speedrun

Sweep Line (Line Sweep)

Built on
Merge IntervalsBreak each interval into a start event and an end event, sort the events, and track how many are open.
The problem

Meeting Rooms II (LC 253)(opens leetcode.com)

You're given an array of meeting time intervals intervals, each entry [start_i, end_i]. Figure out the smallest number of conference rooms that lets every meeting happen -- no room may host two meetings whose times actually overlap (a meeting ending at end_i and another starting at start_j don't overlap once end_i <= start_j).

Example 1
Input:intervals = [[0,30],[5,10],[15,20]]
Output:2
[0,30] overlaps both other meetings, but those two do not overlap each other, so 2 rooms are enough.
[0, 30][5, 10][15, 20]030

Sweep Line

events (start: +1, end: -1) ➔ sort time with end before start ➔ max active count
Spot it when: You need the largest number of intervals overlapping at any moment: meeting rooms, passengers in a car, bookings against a capacity.
Sweep Line
Python
1def min_meeting_rooms(intervals: list[list[int]]) -> int:
2 """Sweep-Line Event Processing: minimum conference rooms required.
3 Time: O(N log N) | Space: O(N)
4 """
5 # 1. Turn Each Interval into Two Point Events:
6 # Only the running count of meetings in progress matters, not which meeting holds which room,
7 # so every interval becomes a +1 event at its start and a -1 event at its end.
8 events: list[tuple[int, int]] = []
9 for start, end in intervals:
10 events.append((start, 1)) # Room checkout: +1
11 events.append((end, -1)) # Room vacated: -1
12 
13 # 2. Sort Events by Time, Ends Before Starts on a Tie:
14 # Meetings are half-open [start, end): at a shared time the -1 must be applied before the +1, so
15 # a meeting ending at that time and one starting at it never count as two rooms at once.
16 events.sort(key=lambda ev: (ev[0], ev[1]))
17 
18 active_rooms = 0 # active_rooms is how many meetings are in progress right after the current event
19 max_rooms = 0 # max_rooms is the highest value active_rooms has reached
20 
21 # 3. Sweep the Timeline and Track the Peak:
22 # Each event changes active_rooms by exactly one, so checking right after every event sees every
23 # value active_rooms ever takes, including its peak.
24 for time, delta in events:
25 active_rooms += delta
26 max_rooms = max(max_rooms, active_rooms)
27 
28 return max_rooms
Invariant: Once all events up to time are applied, active_rooms is the number of meetings in progress, and max_rooms is the highest value it has reached.

Turn each interval into two events, +1 at its start and -1 at its end. Sort the events by time and add them up in order: the running total is how many intervals are active at that moment, and its highest value is the peak. In the blueprint active_rooms is that running total and max_rooms its peak. The trap is a tie: when one meeting ends at the same time another starts, the -1 must be applied first, which sorting by (time, delta) does because -1 < 1; otherwise the room is counted twice.

See it run

Sweep Line, step by step

active_rooms 0 · max_rooms 0

active_rooms 1 · max_rooms 1

active_rooms 2 · max_rooms 2

active_rooms 1 · max_rooms 2

active_rooms 2 · max_rooms 2

active_rooms 1 · max_rooms 2

active_rooms 0 · max_rooms 2

active_rooms 0 · max_rooms 2 · answer 2

Each column is one time point. Each row of numbers is one meeting. A dash marks the time points the meeting covers. The last row fills in as the events are applied.

  • +1 a start event, applied now
  • -1 an end event, applied now
  • active the value of active_rooms right after this event

Each meeting gives two events. Sorted by (time, delta): (0, 1), (2, 1), (6, -1), (6, 1), (8, -1), (9, -1).

Event (0, 1): active_rooms goes from 0 to 1. max_rooms becomes 1.

Event (2, 1): active_rooms goes from 1 to 2. max_rooms becomes 2.

Event (6, -1): active_rooms goes from 2 to 1. Another meeting starts at 6 too, but the -1 comes first.

Event (6, 1): active_rooms goes from 1 to 2. The meeting that ended at 6 has already left its room.

Event (8, -1): active_rooms goes from 2 to 1. max_rooms stays 2.

Event (9, -1): active_rooms goes from 1 to 0. max_rooms stays 2.

Done: the most meetings in progress at once is 2, so 2 rooms are needed.

[0, 6]
0-
1-
2-
3-
4-
5-
6-
7
8
9
[2, 8]
-
-
-
-
-
-
-
[6, 9]
-
-
-
-
active_rooms
1 / 8
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Sorting the events by time alone

    Mistake
    events.sort(key=lambda ev: ev[0])
    Fix
    events.sort(key=lambda ev: (ev[0], ev[1]))

    What happens: A meeting [start, end) is over at end, so a room is free again at that time. When one meeting ends as another starts, the -1 must come first. A key on the time alone keeps tied events in input order. A +1 can then come before the -1, and one room is counted twice.

    Example: intervals = [[10, 20], [0, 10]]
    Mistake: returns 2Fix: returns 1
  2. 2

    Gotcha 2: Putting the +1 before the -1 on a tie

    Mistake
    events.sort(key=lambda ev: (ev[0], -ev[1]))
    Fix
    events.sort(key=lambda ev: (ev[0], ev[1]))

    What happens: The key (ev[0], -ev[1]) puts starts before ends at the same time. Then a meeting starts before the meeting that ends at that time has left its room. The count goes one too high. This order is right only when a meeting still uses its room at its end time.

    Example: intervals = [[0, 10], [10, 20]]
    Mistake: returns 2Fix: returns 1
  3. 3

    Gotcha 3: Returning active_rooms instead of max_rooms

    Mistake
    return active_rooms
    Fix
    return max_rooms

    What happens: active_rooms is the number of meetings running at the current time. After the last event, every meeting has ended, so active_rooms is 0. The answer is the highest value it reached, which max_rooms keeps.

    Example: intervals = [[0, 30], [5, 10], [15, 20]]
    Mistake: returns 0Fix: returns 2
Not this one if…
  • Many range updates must be applied and then every position read, as in Corporate Flight Bookings (LC 1109), not just the busiest moment. See Difference Array

Deep Dive

Why only the running count matters

This card builds on the Merge Intervals card. That card joins overlapping intervals into one. This card does not join them. It counts how many intervals are open at each moment.

The question for Meeting Rooms II (LC 253) is the largest number of meetings in progress at one time. It does not matter which meeting uses which room. So each meeting becomes two events: (start, 1) and (end, -1).

After the events are sorted by time, active_rooms += delta gives the number of meetings in progress right after each event. Each event changes the count by exactly one, so checking max_rooms after every event sees every value that active_rooms ever takes.

Example: in LC 253, intervals = [[0, 30], [5, 10], [15, 20]]. The sorted events are (0, 1), (5, 1), (10, -1), (15, 1), (20, -1), (30, -1). The count goes 1, 2, 1, 2, 1, 0. The peak is 2, so the answer is 2.

One trace: the -1 comes first at a tie

The board replays intervals = [[0, 6], [2, 8], [6, 9]]. The first meeting ends at 6 and the third meeting starts at 6.

The events are sorted by (time, delta). At time 6 there are two events, (6, -1) and (6, 1). Since -1 < 1, the -1 comes first. active_rooms goes from 2 to 1, and then back to 2. These two steps are marked as the trap on the board. The peak is 2.

If the +1 came first, active_rooms would go from 2 to 3 and then back to 2. max_rooms would be 3, which is wrong. The first meeting has already ended at 6, so it does not use a room at that time.

The meetings are half-open: [start, end). A meeting uses its room from start up to, but not including, end. This is why the end event is applied first.

Reading the answer, and the other tie rule

The answer is max_rooms, not active_rooms. After the last event, every meeting has ended, so active_rooms is 0.

The tie rule depends on the problem. In Meeting Rooms II (LC 253), a meeting ending at 10 and one starting at 10 can share a room, so the end comes first. For [[0, 10], [10, 20]] the answer is 1. With the +1 first, the loop returns 2.

Some problems count both end points as busy. Then a meeting that ends at 10 still uses its room at 10, and the start must come first. Read the statement of each problem and choose the order of delta in the sort key.

Python compares tuples left to right, so (ev[0], ev[1]) sorts by time first and by delta second. Sorting by ev[0] alone keeps tied events in input order, which can put a +1 before a -1.

The cost, and which problems fit

There are 2N events. Sorting them takes O(N log N) time, and the loop takes O(N) time. The events use O(N) space.

Example: for 1000 meetings, events holds 2000 entries. The loop runs 2000 times.

Any question about the most intervals open at once uses this card. Car Pooling (LC 1094) uses a delta equal to the number of passengers, and the limit is the capacity. Divide Intervals Into Minimum Number of Groups (LC 2406) is the same peak count.

If the coordinates are small, a difference array can replace the sort. Corporate Flight Bookings (LC 1109) adds to diff[first] and subtracts after diff[last], then takes the running sum.

If the question only needs to know whether two intervals overlap, as in Meeting Rooms (LC 252), sorting by start is enough. Use the Merge Intervals card for joined ranges.

60-Second Pitch

"Only the number of meetings in progress matters, so I turn each meeting into two events: +1 at its start and -1 at its end. I sort the events by time. At the same time, I apply the -1 first, because a meeting that ends at that time has already left its room. Then I add up the deltas in order and keep the highest value in max_rooms. That is O(N log N) time for the sort and O(N) space for the 2N events. I check the tie case, a single meeting, and that I return the peak and not the final count."

Common Questions

Why split each interval into two events?

The answer depends only on how many intervals are open at each moment. A +1 event at the start and a -1 event at the end give that count with one pass over sorted events. The pass does not need to know which interval is which.

Why must the -1 come before the +1 at the same time?

In Meeting Rooms II (LC 253), a meeting ends at its end time and frees its room. A meeting that starts at that time can use the same room. If the +1 is applied first, the count goes one too high for a moment, and max_rooms can record a room that is not needed.

What are the time and space complexity?

O(N log N) time, because 2N events are sorted. The loop is O(N). The space is O(N) for events.

How is this different from merging intervals?

Merging joins overlapping intervals into one range and loses how many were open. Sweep line keeps the count. Use merging when the question is about covered time or gaps. Use sweep line when the question is about the peak number of overlaps.

Can you avoid the sort?

Yes, if the time values are small integers. Make an array diff, add 1 at each start, subtract 1 after each end, and take the running sum. This is O(N + T), where T is the range of time values, and it is how Corporate Flight Bookings (LC 1109) is solved.

SWE Reasoning

Spot it

  • The question asks for the largest number of intervals that overlap at one moment.
  • The wording is about capacity: rooms, cars, servers, passengers or bookings at the same time.
  • Which interval holds which resource does not matter. Only the count matters.
  • Merging the intervals would lose the count, because it joins them into one range.
  • The ends are either half-open or closed, and the statement decides whether a shared time point counts twice.

The invariant, step by step

  1. Create events. For each start, end, append (start, 1) and (end, -1).
  2. Sort events by (time, delta). At the same time, the -1 events come before the +1 events.
  3. Set active_rooms = 0 and max_rooms = 0.
  4. For each time, delta in the sorted events, do active_rooms += delta.
  5. Then set max_rooms = max(max_rooms, active_rooms). Each event changes the count by one, so every value is checked.
  6. After all events, active_rooms is the number of meetings in progress right after the event, and max_rooms is the highest value reached. Return max_rooms.

Traps

  • Sorting by time alone. Tied events stay in input order, so a +1 can come before a -1. For [[10, 20], [0, 10]] the loop returns 2 instead of 1.
  • Putting +1 first on a tie. The key (ev[0], -ev[1]) counts a meeting that ends at 10 and one that starts at 10 as two rooms. For [[0, 10], [10, 20]] it returns 2 instead of 1.
  • Returning active_rooms. After the last event it is 0. Return max_rooms.
  • Tracking which meeting holds which room. The question asks only for a count. A list of rooms adds work and gives no extra information.
  • Using the wrong tie rule. A problem with closed intervals needs the start first. Read whether the end time is still busy.

Practice

Canonical LeetCode:Meeting Rooms II (LC 253)Car Pooling (LC 1094)The Skyline Problem (LC 218)My Calendar II (LC 731)Employee Free Time (LC 759)Divide Intervals Into Minimum Number of Groups (LC 2406)My Calendar III (LC 732)
Theory Context•Intervals & Greedy

Builds on Merge Intervals, which you haven’t finished yet.

P1MediumBuilt on Merge Intervals~4 min speedrun

Sweep Line (Line Sweep)

Built on
Merge IntervalsBreak each interval into a start event and an end event, sort the events, and track how many are open.
The problem

Meeting Rooms II (LC 253)(opens leetcode.com)

You're given an array of meeting time intervals intervals, each entry [start_i, end_i]. Figure out the smallest number of conference rooms that lets every meeting happen -- no room may host two meetings whose times actually overlap (a meeting ending at end_i and another starting at start_j don't overlap once end_i <= start_j).

Example 1
Input:intervals = [[0,30],[5,10],[15,20]]
Output:2
[0,30] overlaps both other meetings, but those two do not overlap each other, so 2 rooms are enough.
[0, 30][5, 10][15, 20]030

Sweep Line

events (start: +1, end: -1) ➔ sort time with end before start ➔ max active count
Spot it when: You need the largest number of intervals overlapping at any moment: meeting rooms, passengers in a car, bookings against a capacity.
Sweep Line
Python
1def min_meeting_rooms(intervals: list[list[int]]) -> int:
2 """Sweep-Line Event Processing: minimum conference rooms required.
3 Time: O(N log N) | Space: O(N)
4 """
5 # 1. Turn Each Interval into Two Point Events:
6 # Only the running count of meetings in progress matters, not which meeting holds which room,
7 # so every interval becomes a +1 event at its start and a -1 event at its end.
8 events: list[tuple[int, int]] = []
9 for start, end in intervals:
10 events.append((start, 1)) # Room checkout: +1
11 events.append((end, -1)) # Room vacated: -1
12 
13 # 2. Sort Events by Time, Ends Before Starts on a Tie:
14 # Meetings are half-open [start, end): at a shared time the -1 must be applied before the +1, so
15 # a meeting ending at that time and one starting at it never count as two rooms at once.
16 events.sort(key=lambda ev: (ev[0], ev[1]))
17 
18 active_rooms = 0 # active_rooms is how many meetings are in progress right after the current event
19 max_rooms = 0 # max_rooms is the highest value active_rooms has reached
20 
21 # 3. Sweep the Timeline and Track the Peak:
22 # Each event changes active_rooms by exactly one, so checking right after every event sees every
23 # value active_rooms ever takes, including its peak.
24 for time, delta in events:
25 active_rooms += delta
26 max_rooms = max(max_rooms, active_rooms)
27 
28 return max_rooms
Invariant: Once all events up to time are applied, active_rooms is the number of meetings in progress, and max_rooms is the highest value it has reached.

Turn each interval into two events, +1 at its start and -1 at its end. Sort the events by time and add them up in order: the running total is how many intervals are active at that moment, and its highest value is the peak. In the blueprint active_rooms is that running total and max_rooms its peak. The trap is a tie: when one meeting ends at the same time another starts, the -1 must be applied first, which sorting by (time, delta) does because -1 < 1; otherwise the room is counted twice.

See it run

Sweep Line, step by step

active_rooms 0 · max_rooms 0

active_rooms 1 · max_rooms 1

active_rooms 2 · max_rooms 2

active_rooms 1 · max_rooms 2

active_rooms 2 · max_rooms 2

active_rooms 1 · max_rooms 2

active_rooms 0 · max_rooms 2

active_rooms 0 · max_rooms 2 · answer 2

Each column is one time point. Each row of numbers is one meeting. A dash marks the time points the meeting covers. The last row fills in as the events are applied.

  • +1 a start event, applied now
  • -1 an end event, applied now
  • active the value of active_rooms right after this event

Each meeting gives two events. Sorted by (time, delta): (0, 1), (2, 1), (6, -1), (6, 1), (8, -1), (9, -1).

Event (0, 1): active_rooms goes from 0 to 1. max_rooms becomes 1.

Event (2, 1): active_rooms goes from 1 to 2. max_rooms becomes 2.

Event (6, -1): active_rooms goes from 2 to 1. Another meeting starts at 6 too, but the -1 comes first.

Event (6, 1): active_rooms goes from 1 to 2. The meeting that ended at 6 has already left its room.

Event (8, -1): active_rooms goes from 2 to 1. max_rooms stays 2.

Event (9, -1): active_rooms goes from 1 to 0. max_rooms stays 2.

Done: the most meetings in progress at once is 2, so 2 rooms are needed.

[0, 6]
0-
1-
2-
3-
4-
5-
6-
7
8
9
[2, 8]
-
-
-
-
-
-
-
[6, 9]
-
-
-
-
active_rooms
1 / 8
Gotchas1 of 3

Gotcha 1 of 3

  1. 1
    The trap

    Gotcha 1: Sorting the events by time alone

    Mistake
    events.sort(key=lambda ev: ev[0])
    Fix
    events.sort(key=lambda ev: (ev[0], ev[1]))

    What happens: A meeting [start, end) is over at end, so a room is free again at that time. When one meeting ends as another starts, the -1 must come first. A key on the time alone keeps tied events in input order. A +1 can then come before the -1, and one room is counted twice.

    Example: intervals = [[10, 20], [0, 10]]
    Mistake: returns 2Fix: returns 1
  2. 2

    Gotcha 2: Putting the +1 before the -1 on a tie

    Mistake
    events.sort(key=lambda ev: (ev[0], -ev[1]))
    Fix
    events.sort(key=lambda ev: (ev[0], ev[1]))

    What happens: The key (ev[0], -ev[1]) puts starts before ends at the same time. Then a meeting starts before the meeting that ends at that time has left its room. The count goes one too high. This order is right only when a meeting still uses its room at its end time.

    Example: intervals = [[0, 10], [10, 20]]
    Mistake: returns 2Fix: returns 1
  3. 3

    Gotcha 3: Returning active_rooms instead of max_rooms

    Mistake
    return active_rooms
    Fix
    return max_rooms

    What happens: active_rooms is the number of meetings running at the current time. After the last event, every meeting has ended, so active_rooms is 0. The answer is the highest value it reached, which max_rooms keeps.

    Example: intervals = [[0, 30], [5, 10], [15, 20]]
    Mistake: returns 0Fix: returns 2
Not this one if…
  • Many range updates must be applied and then every position read, as in Corporate Flight Bookings (LC 1109), not just the busiest moment. See Difference Array

Deep Dive

Why only the running count matters

This card builds on the Merge Intervals card. That card joins overlapping intervals into one. This card does not join them. It counts how many intervals are open at each moment.

The question for Meeting Rooms II (LC 253) is the largest number of meetings in progress at one time. It does not matter which meeting uses which room. So each meeting becomes two events: (start, 1) and (end, -1).

After the events are sorted by time, active_rooms += delta gives the number of meetings in progress right after each event. Each event changes the count by exactly one, so checking max_rooms after every event sees every value that active_rooms ever takes.

Example: in LC 253, intervals = [[0, 30], [5, 10], [15, 20]]. The sorted events are (0, 1), (5, 1), (10, -1), (15, 1), (20, -1), (30, -1). The count goes 1, 2, 1, 2, 1, 0. The peak is 2, so the answer is 2.

One trace: the -1 comes first at a tie

The board replays intervals = [[0, 6], [2, 8], [6, 9]]. The first meeting ends at 6 and the third meeting starts at 6.

The events are sorted by (time, delta). At time 6 there are two events, (6, -1) and (6, 1). Since -1 < 1, the -1 comes first. active_rooms goes from 2 to 1, and then back to 2. These two steps are marked as the trap on the board. The peak is 2.

If the +1 came first, active_rooms would go from 2 to 3 and then back to 2. max_rooms would be 3, which is wrong. The first meeting has already ended at 6, so it does not use a room at that time.

The meetings are half-open: [start, end). A meeting uses its room from start up to, but not including, end. This is why the end event is applied first.

Reading the answer, and the other tie rule

The answer is max_rooms, not active_rooms. After the last event, every meeting has ended, so active_rooms is 0.

The tie rule depends on the problem. In Meeting Rooms II (LC 253), a meeting ending at 10 and one starting at 10 can share a room, so the end comes first. For [[0, 10], [10, 20]] the answer is 1. With the +1 first, the loop returns 2.

Some problems count both end points as busy. Then a meeting that ends at 10 still uses its room at 10, and the start must come first. Read the statement of each problem and choose the order of delta in the sort key.

Python compares tuples left to right, so (ev[0], ev[1]) sorts by time first and by delta second. Sorting by ev[0] alone keeps tied events in input order, which can put a +1 before a -1.

The cost, and which problems fit

There are 2N events. Sorting them takes O(N log N) time, and the loop takes O(N) time. The events use O(N) space.

Example: for 1000 meetings, events holds 2000 entries. The loop runs 2000 times.

Any question about the most intervals open at once uses this card. Car Pooling (LC 1094) uses a delta equal to the number of passengers, and the limit is the capacity. Divide Intervals Into Minimum Number of Groups (LC 2406) is the same peak count.

If the coordinates are small, a difference array can replace the sort. Corporate Flight Bookings (LC 1109) adds to diff[first] and subtracts after diff[last], then takes the running sum.

If the question only needs to know whether two intervals overlap, as in Meeting Rooms (LC 252), sorting by start is enough. Use the Merge Intervals card for joined ranges.

60-Second Pitch

"Only the number of meetings in progress matters, so I turn each meeting into two events: +1 at its start and -1 at its end. I sort the events by time. At the same time, I apply the -1 first, because a meeting that ends at that time has already left its room. Then I add up the deltas in order and keep the highest value in max_rooms. That is O(N log N) time for the sort and O(N) space for the 2N events. I check the tie case, a single meeting, and that I return the peak and not the final count."

Common Questions

Why split each interval into two events?

The answer depends only on how many intervals are open at each moment. A +1 event at the start and a -1 event at the end give that count with one pass over sorted events. The pass does not need to know which interval is which.

Why must the -1 come before the +1 at the same time?

In Meeting Rooms II (LC 253), a meeting ends at its end time and frees its room. A meeting that starts at that time can use the same room. If the +1 is applied first, the count goes one too high for a moment, and max_rooms can record a room that is not needed.

What are the time and space complexity?

O(N log N) time, because 2N events are sorted. The loop is O(N). The space is O(N) for events.

How is this different from merging intervals?

Merging joins overlapping intervals into one range and loses how many were open. Sweep line keeps the count. Use merging when the question is about covered time or gaps. Use sweep line when the question is about the peak number of overlaps.

Can you avoid the sort?

Yes, if the time values are small integers. Make an array diff, add 1 at each start, subtract 1 after each end, and take the running sum. This is O(N + T), where T is the range of time values, and it is how Corporate Flight Bookings (LC 1109) is solved.

SWE Reasoning

Spot it

  • The question asks for the largest number of intervals that overlap at one moment.
  • The wording is about capacity: rooms, cars, servers, passengers or bookings at the same time.
  • Which interval holds which resource does not matter. Only the count matters.
  • Merging the intervals would lose the count, because it joins them into one range.
  • The ends are either half-open or closed, and the statement decides whether a shared time point counts twice.

The invariant, step by step

  1. Create events. For each start, end, append (start, 1) and (end, -1).
  2. Sort events by (time, delta). At the same time, the -1 events come before the +1 events.
  3. Set active_rooms = 0 and max_rooms = 0.
  4. For each time, delta in the sorted events, do active_rooms += delta.
  5. Then set max_rooms = max(max_rooms, active_rooms). Each event changes the count by one, so every value is checked.
  6. After all events, active_rooms is the number of meetings in progress right after the event, and max_rooms is the highest value reached. Return max_rooms.

Traps

  • Sorting by time alone. Tied events stay in input order, so a +1 can come before a -1. For [[10, 20], [0, 10]] the loop returns 2 instead of 1.
  • Putting +1 first on a tie. The key (ev[0], -ev[1]) counts a meeting that ends at 10 and one that starts at 10 as two rooms. For [[0, 10], [10, 20]] it returns 2 instead of 1.
  • Returning active_rooms. After the last event it is 0. Return max_rooms.
  • Tracking which meeting holds which room. The question asks only for a count. A list of rooms adds work and gives no extra information.
  • Using the wrong tie rule. A problem with closed intervals needs the start first. Read whether the end time is still busy.

Practice

Canonical LeetCode:Meeting Rooms II (LC 253)Car Pooling (LC 1094)The Skyline Problem (LC 218)My Calendar II (LC 731)Employee Free Time (LC 759)Divide Intervals Into Minimum Number of Groups (LC 2406)My Calendar III (LC 732)
© 2026 Hi👋WebEnterprise. All rights reserved.
Sitemap•llms.txt•