#57 - Insert Interval
Insert Interval
- Difficulty: Medium
- Topics: Array
- Link: https://leetcode.com/problems/insert-interval/
Problem Description
You are given an array of non-overlapping intervals intervals
where intervals[i] = [starti, endi]
represent the start and the end of the ith
interval and intervals
is sorted in ascending order by starti
. You are also given an interval newInterval = [start, end]
that represents the start and end of another interval.
Insert newInterval
into intervals
such that intervals
is still sorted in ascending order by starti
and intervals
still does not have any overlapping intervals (merge overlapping intervals if necessary).
Return intervals
after the insertion.
Note that you don’t need to modify intervals
in-place. You can make a new array and return it.
Example 1:
Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
Output: [[1,5],[6,9]]
Example 2:
Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
Output: [[1,2],[3,10],[12,16]]
Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].
Constraints:
0 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 105
intervals
is sorted bystarti
in ascending order.newInterval.length == 2
0 <= start <= end <= 105
Solution
1. Problem Deconstruction
Technical Restatement
Given a sorted array intervals
of non-overlapping closed intervals where intervals[i] = [start_i, end_i]
and start_i ≤ end_i
, and a newInterval = [start, end]
, insert newInterval
into intervals
while preserving:
- Sorted Order: The result must remain sorted by ascending
start_i
. - Non-Overlapping: Merge any overlapping intervals into consolidated intervals.
Return a new array (no in-place modification required).
Beginner-Friendly Explanation
Imagine you have a list of time periods (like meetings) that don’t overlap and are sorted by start time. You need to add a new time period to this list. If the new period overlaps with any existing ones, combine them into a single continuous period. Keep the final list sorted and free of overlaps.
Example:
- Original meetings:
[[1,3], [6,9]]
- New meeting:
[2,5]
(overlaps with[1,3]
) - Result:
[[1,5], [6,9]]
(combined[1,3]
and[2,5]
into[1,5]
).
Mathematical Formulation
Let be a set of intervals where and (sorted), and be the new interval. The goal is to compute:
where and are disjoint.
Constraint Analysis
0 ≤ intervals.length ≤ 10^4
:- Empty input → return
[newInterval]
. - Large input → requires or algorithm.
- Empty input → return
0 ≤ start_i ≤ end_i ≤ 10^5
:- Intervals are non-negative; handle cases where
newInterval
starts before/after all existing intervals.
- Intervals are non-negative; handle cases where
- Sorted Order:
- Leverage binary properties; no need for explicit sorting after insertion.
- Non-Overlapping Input:
- Merging only occurs between
newInterval
and existing intervals, never between existing intervals alone.
- Merging only occurs between
2. Intuition Scaffolding
Real-World Metaphor
Like merging train schedules: You have a timetable of non-overlapping train departures (intervals
). Adding a new train (newInterval
) might extend existing slots if arrival/departure times overlap. The station master combines overlapping slots into continuous blocks.
Gaming Analogy
In a strategy game, each interval is a troop deployment phase. Inserting a new deployment phase requires merging overlapping phases (e.g., archers deployed from [4,8]
merging with infantry at [3,5]
and cavalry at [6,10]
→ consolidated deployment [3,10]
).
Mathematical Analogy
Finding the connected components in a 1D number line where nodes are intervals. Inserting newInterval
creates new edges (overlaps), requiring recomputation of the component’s min/max bounds.
Common Pitfalls
- Ignoring Partial Overlaps:
[1,5]
and[3,7]
→ should merge to[1,7]
, not[1,5] + [3,7]
.
- Edge-Overlap Miss:
[1,5]
and[5,10]
should merge to[1,10]
(edge-touching intervals).
- Incorrect Insertion Position:
- Inserting
[2,3]
into[[1,4],[5,6]]
must merge with[1,4]
, not create a new entry.
- Inserting
- Unmerged Disjoint Intervals:
- Failing to merge multiple intervals (e.g.,
newInterval = [4,8]
merging[3,5]
,[6,7]
,[8,10]
).
- Failing to merge multiple intervals (e.g.,
- Boundary Blindness:
newInterval = [0,0]
should not merge with[1,2]
since0 < 1
.
3. Approach Encyclopedia
Brute Force
- Append
newInterval
tointervals
. - Sort by
start_i
(). - Traverse and merge overlaps: if
curr.end >= next.start
, merge to[curr.start, max(curr.end, next.end)]
.
Pseudocode:
def insert(intervals, newInterval):
intervals.append(newInterval)
intervals.sort(key=lambda x: x[0]) # O(n log n)
merged = []
for interval in intervals:
if not merged or merged[-1][1] < interval[0]:
merged.append(interval)
else:
merged[-1][1] = max(merged[-1][1], interval[1])
return merged
Complexity: Time (sorting dominates), Space .
Visualization:
Original: [[1,2], [3,5], [6,7], [8,10], [12,16]] + [4,8]
Append: [[1,2], [3,5], [6,7], [8,10], [12,16], [4,8]]
Sort: [[1,2], [3,5], [4,8], [6,7], [8,10], [12,16]]
Merge: [[1,2]] → [[1,2],[3,5]] → merge [3,5] & [4,8] → [3,8]
→ merge [3,8] & [6,7] → [3,8] → merge [3,8] & [8,10] → [3,10] → add [12,16]
Output: [[1,2], [3,10], [12,16]]
Optimal Approach (Linear Scan)
- Phase 1: Add intervals ending before
newInterval
starts (no overlap). - Phase 2: Merge all intervals overlapping with
newInterval
by updatingnewInterval = [min(start), max(end)]
. - Phase 3: Add remaining intervals.
Pseudocode:
def insert(intervals, newInterval):
merged = []
i, n = 0, len(intervals)
# Phase 1: Non-overlapping left intervals
while i < n and intervals[i][1] < newInterval[0]:
merged.append(intervals[i])
i += 1
# Phase 2: Merge overlaps
while i < n and intervals[i][0] <= newInterval[1]:
newInterval[0] = min(newInterval[0], intervals[i][0])
newInterval[1] = max(newInterval[1], intervals[i][1])
i += 1
merged.append(newInterval)
# Phase 3: Non-overlapping right intervals
while i < n:
merged.append(intervals[i])
i += 1
return merged
Complexity Proof:
- Time: (single pass through
intervals
). - Space: (output storage).
Derivation: Each interval processed exactly once → steps × work/step.
Visualization:
Example: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
Phase 1: [1,2] (2<4) → add. i=1.
Phase 2:
[3,5]: 3 <= 8 → newInterval = [min(4,3)=3, max(8,5)=8] → i=2
[6,7]: 6 <= 8 → newInterval = [3, max(8,7)=8] → i=3
[8,10]: 8 <= 8 → newInterval = [3, max(8,10)=10] → i=4
[12,16]: 12 > 10 → break. Add [3,10].
Phase 3: Add [12,16].
Output: [[1,2],[3,10],[12,16]]
4. Code Deep Dive
Optimal Solution
def insert(intervals, newInterval):
merged = [] # Output list
i, n = 0, len(intervals)
# 1. Add intervals ending before newInterval starts
while i < n and intervals[i][1] < newInterval[0]:
merged.append(intervals[i])
i += 1
# 2. Merge overlapping intervals
while i < n and intervals[i][0] <= newInterval[1]:
newInterval[0] = min(newInterval[0], intervals[i][0])
newInterval[1] = max(newInterval[1], intervals[i][1])
i += 1
merged.append(newInterval)
# 3. Add remaining intervals
while i < n:
merged.append(intervals[i])
i += 1
return merged
Line-by-Line Annotation
- Line 2: Initialize output list and pointers.
- Lines 5-7: Add intervals with
end < newInterval.start
(no overlap). - Lines 10-12: Expand
newInterval
to cover all overlapping intervals.intervals[i][0] <= newInterval[1]
checks for overlap.
- Line 13: Add the merged interval.
- Lines 16-18: Append remaining non-overlapping intervals.
Edge Case Handling
- Empty Input (
intervals = []
):
Skips Phases 1/2, appendsnewInterval
(Line 13). newInterval
at Start (newInterval = [0,1]
,intervals = [[1,2]]
):
Phase 1 skipped (noend < 0
). Phase 2:[1,2]
overlaps?1 <= 1
→ merge to[0,2]
.newInterval
at End (intervals = [[1,2]]
,newInterval = [3,4]
):
Phase 1: Add[1,2]
. Phase 2: No overlap (3 > 2
). Append[3,4]
in Phase 3.- Full Overlap (
newInterval = [0,10]
,intervals = [[1,2],[3,4]]
):
Phase 1: No adds. Phase 2: Merges all into[0,10]
.
5. Complexity War Room
Hardware-Aware Analysis
- Time: → 10,000 steps at 1GHz ≈ 0.01ms (negligible).
- Space: → 10,000 intervals × 2 integers × 4B = 80KB (fits in CPU L3 cache).
Industry Comparison Table
Approach | Time | Space | Readability | Interview Viability |
---|---|---|---|---|
Brute Force | High (9/10) | ❌ Large | ||
Optimal (Scan) | High (8/10) | ✅ Preferred |
6. Pro Mode Extras
Variants
- Insert and Merge with Existing Overlaps (Hard):
Inputintervals
may have overlaps. Solution: First merge all existing intervals, then insert. - Multiple New Intervals (LC 715. Range Module):
Support adding/removing intervals. Solution: Balanced BST or Segment Tree. - Maximum Overlapping Intervals After Insertion (LC 253. Meeting Rooms II):
Compute min rooms needed after insertion. Solution: Sweep line + heap.
Interview Cheat Sheet
- First Mention: Time/space complexity.
- Key Insight: Three-phase linear scan avoids sorting.
- Verification: Test with:
newInterval
before all, after all, merges multiple, no merge.
- Optimization: Binary search for Phase 1 (but still for merging).