Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find intervals by merging target interval in Python
Suppose we have a list of non-overlapping intervals sorted by end time. We need to merge a target interval into this list while maintaining the non-overlapping and sorted properties.
For example, if we have intervals = [[1, 15], [25, 35], [75, 90]] and target = [10, 30], the output will be [[1, 35], [75, 90]] because the target interval [10, 30] overlaps with both [1, 15] and [25, 35], merging them into a single interval [1, 35].
Algorithm
To solve this problem, we follow these steps:
Add the target interval to the list of intervals
Sort all intervals by their start time
Initialize result list with the first interval
-
For each remaining interval:
If it overlaps with the last interval in result, merge them
Otherwise, add it to the result
Implementation
class Solution:
def solve(self, intervals, target):
# Add target interval to the list
intervals.append(target)
# Sort intervals by start time
intervals.sort(key=lambda x: x[0])
# Initialize result with first interval
result = [intervals[0]]
# Process remaining intervals
for i in range(1, len(intervals)):
current_interval = intervals[i]
last_result = result[-1]
# Check if current interval overlaps with last merged interval
if current_interval[0] <= last_result[1]:
# Merge intervals by extending the end time
last_result[1] = max(last_result[1], current_interval[1])
else:
# No overlap, add current interval to result
result.append(current_interval)
return result
# Test the solution
solution = Solution()
intervals = [[1, 15], [25, 35], [75, 90]]
target = [10, 30]
print("Original intervals:", intervals)
print("Target interval:", target)
print("Merged intervals:", solution.solve(intervals.copy(), target))
Original intervals: [[1, 15], [25, 35], [75, 90]] Target interval: [10, 30] Merged intervals: [[1, 35], [75, 90]]
How It Works
Let's trace through the example step by step:
def merge_intervals_step_by_step(intervals, target):
print(f"Step 1: Original intervals: {intervals}")
print(f"Step 2: Target interval: {target}")
# Add target to intervals
intervals.append(target)
print(f"Step 3: After adding target: {intervals}")
# Sort by start time
intervals.sort(key=lambda x: x[0])
print(f"Step 4: After sorting: {intervals}")
# Merge overlapping intervals
result = [intervals[0]]
print(f"Step 5: Initialize result: {result}")
for i, interval in enumerate(intervals[1:], 1):
print(f"Step {5+i}: Processing {interval}")
if interval[0] <= result[-1][1]:
old_end = result[-1][1]
result[-1][1] = max(result[-1][1], interval[1])
print(f" ? Overlaps! Merge: extend end from {old_end} to {result[-1][1]}")
else:
result.append(interval)
print(f" ? No overlap, add to result")
print(f" ? Current result: {result}")
return result
intervals = [[1, 15], [25, 35], [75, 90]]
target = [10, 30]
final_result = merge_intervals_step_by_step(intervals.copy(), target)
print(f"Final result: {final_result}")
Step 1: Original intervals: [[1, 15], [25, 35], [75, 90]] Step 2: Target interval: [10, 30] Step 3: After adding target: [[1, 15], [25, 35], [75, 90], [10, 30]] Step 4: After sorting: [[1, 15], [10, 30], [25, 35], [75, 90]] Step 5: Initialize result: [[1, 15]] Step 6: Processing [10, 30] ? Overlaps! Merge: extend end from 15 to 30 ? Current result: [[1, 30]] Step 7: Processing [25, 35] ? Overlaps! Merge: extend end from 30 to 35 ? Current result: [[1, 35]] Step 8: Processing [75, 90] ? No overlap, add to result ? Current result: [[1, 35], [75, 90]] Final result: [[1, 35], [75, 90]]
Alternative Approach
Here's a more functional approach using built-in Python functions:
def merge_target_interval(intervals, target):
# Combine and sort intervals
all_intervals = sorted(intervals + [target], key=lambda x: x[0])
# Merge overlapping intervals
merged = []
for start, end in all_intervals:
if merged and start <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], end)
else:
merged.append([start, end])
return merged
# Test with different examples
test_cases = [
([[1, 15], [25, 35], [75, 90]], [10, 30]),
([[1, 3], [6, 9]], [2, 5]),
([[1, 4], [6, 8]], [10, 12])
]
for intervals, target in test_cases:
result = merge_target_interval(intervals, target)
print(f"Intervals: {intervals}, Target: {target} ? Result: {result}")
Intervals: [[1, 15], [25, 35], [75, 90]], Target: [10, 30] ? Result: [[1, 35], [75, 90]] Intervals: [[1, 3], [6, 9]], Target: [2, 5] ? Result: [[1, 9]] Intervals: [[1, 4], [6, 8]], Target: [10, 12] ? Result: [[1, 4], [6, 8], [10, 12]]
Conclusion
This algorithm efficiently merges a target interval into a sorted list of non-overlapping intervals. The key insight is to sort all intervals by start time and then merge overlapping intervals in a single pass, maintaining O(n log n) time complexity due to sorting.
