Insert Interval into Sorted List in DSA Rust - Time & Space Complexity
We want to understand how long it takes to add a new time interval into a list of sorted intervals.
Specifically, how the time grows as the list gets bigger.
Analyze the time complexity of the following code snippet.
fn insert_interval(intervals: &mut Vec<(i32, i32)>, new_interval: (i32, i32)) {
let mut result = Vec::new();
let mut i = 0;
let n = intervals.len();
while i < n && intervals[i].1 < new_interval.0 {
result.push(intervals[i]);
i += 1;
}
let mut merged = new_interval;
while i < n && intervals[i].0 <= merged.1 {
merged.0 = std::cmp::min(merged.0, intervals[i].0);
merged.1 = std::cmp::max(merged.1, intervals[i].1);
i += 1;
}
result.push(merged);
while i < n {
result.push(intervals[i]);
i += 1;
}
*intervals = result;
}
This code inserts a new interval into a sorted list of intervals, merging any overlapping intervals.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Three while loops that each traverse parts of the intervals list.
- How many times: Each loop runs over a portion of the list without overlap, together covering all intervals once.
As the number of intervals grows, the code checks each interval once in order.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks and merges |
| 100 | About 100 checks and merges |
| 1000 | About 1000 checks and merges |
Pattern observation: The operations grow roughly in direct proportion to the number of intervals.
Time Complexity: O(n)
This means the time to insert and merge intervals grows linearly with the number of intervals in the list.
[X] Wrong: "Since there are three loops, the time complexity is O(3n) or O(n^2)."
[OK] Correct: The loops run one after another without overlapping intervals, so together they only pass through the list once, keeping the time linear, not quadratic.
Understanding this linear time complexity helps you explain how to efficiently handle sorted data and merging tasks, a common real-world problem.
"What if the intervals list was not sorted? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem context
We have a sorted list of intervals and want to insert a new interval without breaking the order.Step 2: Identify the required operation
We must insert the new interval and merge any intervals that overlap with it to keep the list sorted and non-overlapping.Final Answer:
To add the new interval and merge any overlapping intervals -> Option DQuick Check:
Insert and merge intervals = To add the new interval and merge any overlapping intervals [OK]
- Replacing all intervals instead of merging
- Sorting intervals in descending order
- Removing intervals before the new one
Solution
Step 1: Identify correct Rust tuple and vector syntax
Rust uses (i32, i32) for tuple of two integers and Vec for vector type.Step 2: Check each option
let intervals: Vec<(i32, i32)> = vec![(1, 3), (6, 9)]; uses Vec<(i32, i32)> with vec! macro and tuples correctly. let intervals = [(1, 3), (6, 9)]; is an array, not a vector. let intervals: Vec<[i32; 2]> = vec![[1, 3], [6, 9]]; uses arrays inside vector, which is valid but different type. let intervals: Vec<(int, int)> = vec![(1, 3), (6, 9)]; uses 'int' which is invalid in Rust.Final Answer:
let intervals: Vec<(i32, i32)> = vec![(1, 3), (6, 9)]; -> Option AQuick Check:
Correct Rust tuple vector syntax = let intervals: Vec<(i32, i32)> = vec![(1, 3), (6, 9)]; [OK]
- Using 'int' instead of 'i32'
- Confusing arrays and tuples
- Not using vec! macro for vectors
vec![(1, 3), (6, 9)] and a new interval (2, 5), what is the resulting list after insertion and merging?Solution
Step 1: Insert new interval and find overlaps
The new interval (2, 5) overlaps with (1, 3) because 2 <= 3.Step 2: Merge overlapping intervals
Merge (1, 3) and (2, 5) into (1, 5). The interval (6, 9) remains unchanged.Final Answer:
[(1, 5), (6, 9)] -> Option CQuick Check:
Merged intervals = [(1, 5), (6, 9)] [OK]
- Not merging overlapping intervals
- Inserting without sorting
- Merging all intervals incorrectly
fn insert_interval(intervals: &mut Vec<(i32, i32)>, new_interval: (i32, i32)) {
let mut i = 0;
while i < intervals.len() {
if intervals[i].1 < new_interval.0 {
i += 1;
} else if intervals[i].0 > new_interval.1 {
intervals.insert(i, new_interval);
return;
} else {
intervals[i].0 = intervals[i].0.min(new_interval.0);
intervals[i].1 = intervals[i].1.max(new_interval.1);
intervals.remove(i + 1);
}
}
intervals.push(new_interval);
}
What is the main bug in this code?Solution
Step 1: Examine the else branch for merging
The code updates intervals[i] by merging the new interval but never increments the index i inside the else block.Step 2: Identify infinite loop cause
Because i is not incremented after merging and removing intervals[i+1], the loop can get stuck processing the same index repeatedly, causing an infinite loop.Final Answer:
It never increments index i inside the else block causing infinite loop -> Option AQuick Check:
Missing i increment in else block = infinite loop [OK]
- Forgetting to increment index after removal
- Assuming insert always works without checks
- Ignoring empty vector edge case
vec![(1, 2), (3, 5), (6, 7), (8, 10), (12, 16)]. Insert the new interval (4, 8) and return the updated list after merging all overlapping intervals.Solution
Step 1: Identify intervals overlapping with (4, 8)
Intervals (3, 5), (6, 7), and (8, 10) overlap with (4, 8) because their ranges intersect.Step 2: Merge all overlapping intervals
Merge (3, 5), (6, 7), (8, 10), and (4, 8) into one interval (3, 10). The intervals (1, 2) and (12, 16) remain unchanged.Final Answer:
[(1, 2), (3, 10), (12, 16)] -> Option BQuick Check:
Merged intervals after insertion = [(1, 2), (3, 10), (12, 16)] [OK]
- Merging only partially overlapping intervals
- Not merging intervals that touch at boundaries
- Replacing intervals incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
