intermediate8 min read·Updated September 20, 2026

Insert Interval Explained: Adding [2, 5] to [[1, 3], [6, 9]]

Master interval insertion with a step-by-step walkthrough of inserting [2, 5] into [[1, 3], [6, 9]]. Learn the 3-phase mental model to handle merges.

By Learnisim AI·Published September 20, 2026
LEARNING ARCSetup → Model in the example → Full trace → Twist → Edge cases → Apply
PREREQUISITES
  • Basic array manipulation
  • Understanding interval overlaps
Interval Insertion: The Three-Phase Assembly Line Phase 1: Left (Pass-Through) Copy intervals ending strictly before new interval starts. End < NewStart Phase 2: Merge (Overlap) Expand bubble: min(start), max(end) while overlapping. Merge & absorb blocks Phase 3: Right (Tail) Dump all remaining intervals untouched into result array. Guaranteed sorted & disjoint Case A: Insert [2, 5] into [[1,3], [6,9]] [1, 3] New [2, 5] [6, 9] Step 1 & 2 (Left & Merge): [1,3] overlaps [2,5] → min(1,2)=1, max(3,5)=5 ⇒ [1,5] Step 3 (Right Tail): [6,9] does not overlap [1,5] (6 > 5). Append remainder. Result: [[1, 5], [6, 9]] Case B: Insert [4, 8] into 5 intervals [1,2] [3,5] [6,7] [8,10] [12,16] New [4, 8] Step 1 & 2 (Left & Merge): [1,2] kept. [3,5], [6,7], [8,10] overlap → merged to [3,10] Step 3 (Right Tail): [12,16] safe past 10. Append directly. Result: [[1,2], [3,10], [12,16]]
Insert [2, 5] into [[1,3],[6,9]] and [4, 8] into [[1,2],[3,5],[6,7],[8,10],[12,16]] overview diagram
Why

Why simple interval insertion gets messy fast

Phase 1: The Scheduling Nightmare

Imagine you are building a calendar app. You have a sorted list of busy times—our Given data: Case A starts with [[1,3],[6,9]] and Case B with [[1,2],[3,5],[6,7],[8,10],[12,16]]. Suddenly, a user tries to book a new block of time. In Case A, you need to insert . In Case B, you need to insert .
If you just blindly push the new interval onto the end of the list, your schedule becomes unsorted and invalid. If you scan the list and try to fix overlaps by hand with nested loops or arbitrary index shifting, edge cases multiply. What if the new interval bridges three existing blocks together? What if it falls entirely in a blank gap between meetings?
Without a structured mental model for how intervals relate, code turns into an unreadable maze of if-else statements. We need a systematic way to process sorted, disjoint intervals without constantly backtracking.
Why Simple Interval Insertion Gets Messy Fast Case A: Single Overlap & Merge Given: [[1, 3], [6, 9]] | Insert: [2, 5] 0 1 2 3 4 5 6 7 8 9 [1, 3] [6, 9] Insert: [2, 5] Result A (Merged): [1, 5] (bridges [1,3] & [2,5]) [6, 9] Case B: The Scheduling Nightmare (Multiple Overlaps & Index Shifting) Insert: [4, 8] into 5 existing blocks 0 2 3 4 5 6 7 8 10 12 16 [1,2] [3,5] [6,7] [8,10] [12,16] Insert: [4, 8] (Overlaps 4 existing blocks!) Result B (Fully Merged): [1,2] [3, 10] (Merged 4 blocks!) [12,16] The Trap: Manual index shifting & nested loops fail when 1 new interval swallows 3+ existing blocks. Solution: 3-phase clean algorithm -> (1) Add all strictly before, (2) Merge all overlapping, (3) Add all strictly after.
Why simple interval insertion gets messy fast diagram
Model

The Three-Phase Mental Model for Interval Insertion

Phase 2: The Timeline Assembly Line

When you look at our working examples, such as inserting into the existing list [[1,3], [6,9]], your intuition shouldn't be to search for a random spot to splice. Instead, imagine an assembly line moving strictly from left to right along a number line. Because the input intervals are already sorted and non-overlapping, we can process them in three distinct chronological blocks.
First, we scan past any intervals that finish strictly before the new interval begins. For instance, in Case A, no intervals end before 2 starts, so this left set is empty. In Case B, where we insert into [[1,2], [3,5], [6,7], [8,10], [12,16]], the interval ends at 2, which is strictly less than the new start of 4. We immediately copy straight to our output without any changes.
Second, we encounter intervals that overlap with our new interval. This is where the merging happens. In Case A, overlaps with because . In Case B, both and overlap with . Instead of adding them separately, we fold them into a single expanding bubble by taking the minimum of the starts and the maximum of the ends. For Case B, this transforms our running interval from to , which becomes , and then further expands when hitting to bridge the gap.
Finally, once we pass all overlapping elements, we dump the remaining tail of the array untouched into our result. This mechanical pass-through works because the original list was already sorted and disjoint, meaning anything to the right of the overlap zone is guaranteed to sit safely past our newly merged block.
Interval Insertion: The Three-Phase Timeline Assembly Line Example: Insert [4, 8] into [[1,2], [3,5], [6,7], [8,10], [12,16]] 1 2 3 4 5 6 7 8 9 10 12 16 New Interval: [4, 8] Phase 1: Strictly Before • Ends before new interval starts • Condition: interval.end < new.start Action: Copy Unchanged Copy [1, 2] directly to output Phase 2: Overlap & Merge • Intersects with new interval • Formula: [ min(S), max(E) ] Action: Expand & Fold Absorbs [3,5], [6,7], [8,10] → [3, 10] Phase 3: Strictly After • Starts after new interval ends • Condition: interval.start > new.end Action: Dump Tail Copy [12, 16] directly to output Final Output Result [1, 2] , [3, 10] , [12, 16] Linear time O(N) scan: Single pass handles all overlap mutations cleanly.
The Three-Phase Mental Model for Interval Insertion diagram
Worked example

Tracing Interval Insertion Step by Step

Phase 3: Walking the Timeline

Let's apply our three-phase mental model to our two canonical cases. We will trace the exact array states as we collect left non-overlapping intervals, merge overlapping ones, and gather the remainder.

Case A Trace: Insert [2, 5] into [[1,3],[6,9]]

- Given: Existing intervals [[1,3],[6,9]], new interval [2,5].
- Step 1 (Left Phase): Check [1,3]. Does it end before 2 (3 < 2)? No. It overlaps, so we stop the left phase. Output so far: [].
- Step 2 (Merge Phase): Process [1,3] and [6,9] while they overlap with [2,5]. Interval [1,3] overlaps [2,5] (since 1 <= 5 and 3 >= 2). We merge them into a single temporary interval: [min(1,2), max(3,5)] = [1,5]. Next, look at [6,9]. Does it overlap [1,5]? No (6 > 5), so the merge phase ends. Current merged interval: [1,5].
- Step 3 (Right Phase): Append all remaining intervals starting from [6,9].
- Result: [[1,5],[6,9]].

Case B Trace: Insert [4, 8] into [[1,2],[3,5],[6,7],[8,10],[12,16]]

- Given: Existing intervals [[1,2],[3,5],[6,7],[8,10],[12,16]], new interval [4,8].
•Step 1 (Left Phase):

- Check [1,2] (): Add to result. Result: [[1,2]].
- Check [3,5] ( is false): Overlap detected, stop left phase.
- Step 2 (Merge Phase): Combine all intervals overlapping [4,8].
- [3,5] overlaps [4,8] new bounds: [min(3,4), max(5,8)] = [3,8].
- [6,7] overlaps [3,8] new bounds: [min(3,6), max(8,7)] = [3,8].
- [8,10] overlaps [3,8] () new bounds: [min(3,8), max(8,10)] = [3,10].
- [12,16] does not overlap [3,10] (), stop merge phase.
- Step 3 (Right Phase): Append [12,16].
- Result: [[1,2],[3,10],[12,16]].
python
def insert(intervals, newInterval):
    result = []
    i = 0
    n = len(intervals)
    
    # Phase 1: Left non-overlapping
    while i < n and intervals[i][1] < newInterval[0]:
        result.append(intervals[i])
        i += 1
        
    # Phase 2: Overlapping merge
    # TODO: write the merge loop for [4,8] spanning [3,5], [6,7], and [8,10]
    
    # Phase 3: Right non-overlapping
    while i < n:
        result.append(intervals[i])
        i += 1
        
    return result
Phase 3 Timeline Walk: Case B Trace Inserting [4, 8] into [[1,2], [3,5], [6,7], [8,10], [12,16]] Timeline 1. Left Phase Ends before 4 [1, 2] Added to Result [3, 5] 5 < 4 False! Stop Left Phase 2. Merge Phase (New: [4, 8]) Absorbs all intervals overlapping [4,8] New: [4, 8] [3, 5] [6, 7] [8, 10] [12, 16] 12 > 10: Stop Merged Result: [min(3), max(10)] = [3, 10] Combines bounds across all overlapping neighbors! 3. Right Phase Collect remainder [12, 16] Appended No more intervals Exit loop & return FINAL RESULT ARRAY (Case B) [[1, 2], [3, 10], [12, 16]]
Tracing Interval Insertion Step by Step diagram
Practice

Test Your Intuition on a Boundary Insertion Case

Phase 4: Practice

Now it is time to test your mental model against a concrete scenario using the same interval logic we traced earlier. Recall how we split our tasks into three phases: collecting left non-overlapping intervals, merging overlapping ones, and appending remaining right-side intervals.
Consider our base list of sorted disjoint intervals: .
Your task is to predict the final merged array when we insert the new interval . Think through which intervals lie completely before 11, which intervals overlap with , and which intervals sit completely after it.
python
intervals = [[1, 2], [3, 5], [6, 7], [8, 10], [12, 16]]
newInterval = [11, 13]
# What is the output of insert(intervals, newInterval)?
Apply

Applying the Three-Phase Template to Neighboring Interval Problems

Phase 5:

Now that you have traced Case A and Case B using our three-phase mental model, it is time to apply this exact pattern to a real-world variation: Meeting Room Booking. Suppose you manage an existing schedule of booked hours represented as intervals, such as [[9, 10], [12, 13], [14, 16]], and a client requests a new booking from [11, 15]. Instead of panicking or writing custom conditional spaghetti for every possible overlap scenario, you can map the request directly onto the three phases you mastered.
First, scan from the left and pass through any existing meetings that finish strictly before the new start time of 11, copying [[9, 10]] directly into your output. Second, hit the overlap zone where meetings collide with 11 or extend into 15: you encounter [12, 13] and [14, 16]. By taking the minimum start () and the maximum end (), you collapse those colliding bookings into a single consolidated time block of [11, 16]. Third, append any remaining future meetings that start strictly after your new end time of 16.
This structural transfer works because every interval insertion problem shares the same underlying geometry. Whether you are merging array chunks in a database query planner or allocating calendar slots, the three-phase invariant—before, during, and after—remains invariant. You never need to reinvent the loop; you just plug your new interval into the three-stage template.
python
def insert_and_book(intervals, new_interval):
    # Apply the three-phase pattern to schedule [[9, 10], [12, 13], [14, 16]] with [11, 15]
    pass

FAQ

What happens when we insert [2, 5] into [[1, 3], [6, 9]]?
We compare [2, 5] with existing intervals. It overlaps with [1, 3] because 2 <= 3, merging them into [1, 5]. It does not overlap with [6, 9] (since 5 < 6), leaving the final result as [[1, 5], [6, 9]].
Why can't we just append the new interval and sort?
Appending and sorting takes O(N log N) time due to the sorting step. By leveraging the fact that the original list is already sorted and disjoint, we can solve interval insertion in O(N) time.
What is the time complexity of the three-phase insertion algorithm?
The time complexity is O(N) where N is the number of intervals, as we iterate through the list at most once. The space complexity is O(N) to store the resulting intervals.

Keep learning