Data Stream as Disjoint Intervals
Expert Answer & Key Takeaways
A complete guide to understanding and implementing Heap / Priority Queue.
Data Stream as Disjoint Intervals
Given a data stream input of non-negative integers
a1, a2, ..., an, summarize the numbers seen so far as a list of disjoint intervals.Implement the
SummaryRanges class:SummaryRanges()Initializes the object with an empty stream.void addNum(int value)Adds the integervalueto the stream.int[][] getIntervals()Returns a summary of the integers in the stream currently as a list of disjoint intervals[start_i, end_i]. The answer should be sorted bystart_i.
Visual Representation
addNum(1): [1,1]
addNum(3): [1,1], [3,3]
addNum(7): [1,1], [3,3], [7,7]
addNum(2): [1,3], [7,7] <-- 2 merges [1,1] and [3,3]
addNum(6): [1,3], [6,7] <-- 6 merges with [7,7]
Key: When adding N, find and merge with adjacent intervals.
[L, N-1] + N + [N+1, R] => [L, R]Examples
Input: ["SummaryRanges", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals", "addNum", "getIntervals"]
[[], [1], [], [3], [], [7], [], [2], [], [6], []]
Output: [null, null, [[1,1]], null, [[1,1],[3,3]], null, [[1,1],[3,3],[7,7]], null, [[1,3],[7,7]], null, [[1,3],[6,7]]]
Approach 1
Level I: Brute Force - Rebuild on Every getIntervals
Intuition
Simply store all seen numbers in a sorted list. On every
getIntervals() call, rebuild the disjoint intervals from scratch by scanning through the sorted list and merging consecutive numbers.⏱ O(N log N) for `addNum` (insert into sorted structure), O(N) for `getIntervals`💾 O(N) for storing all numbers
Detailed Dry Run
addNum(1), addNum(3), addNum(7), addNum(2)
nums = {1, 2, 3, 7}
getIntervals():
sorted = [1, 2, 3, 7]
Scan: 1->next is 2 (consecutive), 2->next is 3 (consecutive), 3->next is 7 (gap)
Intervals: [1,3], [7,7]
Approach 2
Level II: Maintenance of Sorted Intervals
Intuition
Instead of rebuilding the intervals every time, we can maintain a sorted list of disjoint intervals. When adding a new number, we use binary search to find where it would fit among existing intervals, then check if it can be merged with its left or right neighbors. This significantly speeds up
getIntervals at the cost of for addNum due to array shifts.⏱ O(N) for `addNum` (binary search + possible array insertion/deletion), O(1) for `getIntervals` (if returning the internal list)💾 O(N) for storing the intervals
Detailed Dry Run
addNum(1): [[1,1]]
addNum(3): [[1,1], [3,3]]
addNum(2): 2 is between [1,1] and [3,3]. Merges both -> [[1,3]]
addNum(7): [[1,3], [7,7]]
Approach 3
Level III: TreeMap / Sorted Map for O(log N) addNum
Intuition
Instead of re-sorting each time, maintain intervals in a sorted map (TreeMap in Java, SortedDict in Python, etc.) keyed by
start. When adding a new number val:- Find the interval that might start right after
val+1(right neighbor). - Find the interval whose start <=
val(left neighbor), and check if it ends atval-1. - Based on overlapping/adjacency with left and right neighbors, merge intervals accordingly.
This gives
O(log N) per addNum and O(N) per getIntervals.⏱ O(log N) for `addNum`, O(N) for `getIntervals`💾 O(N) for storing the intervals in the sorted map
Detailed Dry Run
addNum(1): map = {1:[1,1]}
addNum(3): map = {1:[1,1], 3:[3,3]}
addNum(7): map = {1:[1,1], 3:[3,3], 7:[7,7]}
addNum(2): val=2.
Right neighbor start=3 (3 == 2+1). Left neighbor: key=1, [1,1]. end=1 == 2-1.
Merge both: [min(1,2)=1, max(1,3)=3] = [1,3]. Remove key 3.
map = {1:[1,3], 7:[7,7]}
addNum(6): val=6.
Right neighbor start=7 (7 == 6+1). Check left: key=1, [1,3]. end=3 != 5.
Only merge with right: [6, 7]. Remove key 7.
map = {1:[1,3], 6:[6,7]}
getIntervals: [[1,3],[6,7]]
Course4All Technical Board
Verified ExpertSenior Software Engineers & Algorithmic Experts
Our DSA content is authored and reviewed by engineers from top tech firms to ensure optimal time and space complexity analysis.
Pattern: 2026 Ready
Updated: Weekly
Found an issue or have a suggestion?
Help us improve! Report bugs or suggest new features on our Telegram group.