|
1 | | -You are given an array of non-overlapping intervals `intervals` where `intervals[i] = [start_i, end_i]` represent the start and the end of the `i^th` interval and `intervals` is sorted in ascending order by `start_i`. You are also given an interval `newInterval = [start, end]` that represents the start and end of another interval. |
2 | | - |
3 | | -Insert `newInterval` into `intervals` such that `intervals` is still sorted in ascending order by `start_i` and `intervals` still does not have any overlapping intervals (merge overlapping intervals if necessary). |
4 | | - |
5 | | -Return `intervals` *after the insertion*. |
6 | | - |
7 | | -**Note** that you don't need to modify `intervals` in-place. You can make a new array and return it. |
8 | | - |
9 | | -**Example 1:** |
10 | | - |
11 | | -```sh |
12 | | -Input: intervals = [[1,3],[6,9]], newInterval = [2,5] |
13 | | -Output: [[1,5],[6,9]] |
14 | | -``` |
15 | | - |
16 | | -**Example 2:** |
17 | | - |
18 | | -```sh |
19 | | -Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] |
20 | | -Output: [[1,2],[3,10],[12,16]] |
21 | | -Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10]. |
22 | | -``` |
23 | | - |
24 | | -**Constraints:** |
| 1 | +## Explanation |
25 | 2 |
|
26 | | -- `0 <= intervals.length <= 10^4` |
27 | | -- `intervals[i].length == 2` |
28 | | -- `0 <= start_i <= end_i <= 10^5` |
29 | | -- `intervals` is sorted by `start_i` in **ascending** order. |
30 | | -- `newInterval.length == 2` |
31 | | -- `0 <= start <= end <= 10^5` |
| 3 | +### Strategy (The "Why") |
32 | 4 |
|
33 | | -## Explanation |
| 5 | +**Restate the problem:** We are given a sorted array of non-overlapping intervals and a new interval. We need to insert the new interval into the array such that the result remains sorted and all overlapping intervals are merged. |
34 | 6 |
|
35 | | -### Strategy |
| 7 | +**1.1 Constraints & Complexity:** |
36 | 8 |
|
37 | | -This is an **array manipulation problem** that requires inserting a new interval into a sorted list of non-overlapping intervals. The key insight is to process intervals in three phases: before overlap, during overlap, and after overlap. |
| 9 | +- **Input Size:** Up to 10^4 intervals, each with start and end values up to 10^5. |
| 10 | +- **Time Complexity:** O(n) where n is the number of intervals. We traverse the array once, processing each interval at most once. |
| 11 | +- **Space Complexity:** O(n) to store the result array. |
| 12 | +- **Edge Case:** If the intervals array is empty, we return an array containing only the new interval. |
38 | 13 |
|
39 | | -**Key observations:** |
40 | | -- Intervals are already sorted by start time |
41 | | -- We need to find where the new interval fits |
42 | | -- We may need to merge multiple overlapping intervals |
43 | | -- Process intervals in three phases based on overlap with new interval |
| 14 | +**1.2 High-level approach:** |
44 | 15 |
|
45 | | -**High-level approach:** |
46 | | -1. **Add intervals before overlap**: Add all intervals that end before new interval starts |
47 | | -2. **Merge overlapping intervals**: Find all intervals that overlap with new interval |
48 | | -3. **Add merged interval**: Add the final merged interval |
49 | | -4. **Add remaining intervals**: Add all intervals that start after new interval ends |
| 16 | +The goal is to process intervals in three phases: add intervals that come before the new interval, merge all intervals that overlap with the new interval, and add the remaining intervals that come after. |
50 | 17 |
|
51 | | -### Steps |
| 18 | +**1.3 Brute force vs. optimized strategy:** |
52 | 19 |
|
53 | | -Let's break down the solution step by step: |
| 20 | +- **Brute Force:** Insert the new interval, sort the entire array, then merge overlapping intervals. This would be O(n log n) time due to sorting. |
| 21 | +- **Optimized Strategy:** Since intervals are already sorted, we can process them in a single pass: add intervals before overlap, merge overlapping ones, then add remaining intervals. This is O(n) time. |
| 22 | +- **Optimization:** By leveraging the fact that intervals are already sorted, we avoid the need for sorting and can process everything in one pass, making the solution more efficient. |
54 | 23 |
|
55 | | -**Step 1: Initialize result list** |
56 | | -- Create empty result list: `result = []` |
| 24 | +**1.4 Decomposition:** |
57 | 25 |
|
58 | | -**Step 2: Add intervals before overlap** |
59 | | -- Add all intervals where `interval[1] < newInterval[0]` |
| 26 | +1. Add all intervals that end before the new interval starts (no overlap). |
| 27 | +2. Merge all intervals that overlap with the new interval by updating the start and end boundaries. |
| 28 | +3. Add the merged interval to the result. |
| 29 | +4. Add all remaining intervals that start after the merged interval ends. |
60 | 30 |
|
61 | | -**Step 3: Merge overlapping intervals** |
62 | | -- Find all intervals that overlap with new interval |
63 | | -- Update new interval boundaries: `start = min(start, interval[0])`, `end = max(end, interval[1])` |
| 31 | +### Steps (The "How") |
64 | 32 |
|
65 | | -**Step 4: Add merged interval** |
66 | | -- Add the final merged interval to result |
| 33 | +**2.1 Initialization & Example Setup:** |
67 | 34 |
|
68 | | -**Step 5: Add remaining intervals** |
69 | | -- Add all intervals where `interval[0] > newInterval[1]` |
| 35 | +Let's use the example: `intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]]`, `newInterval = [4,8]` |
70 | 36 |
|
71 | | -**Example walkthrough:** |
72 | | -Let's trace through the second example: |
| 37 | +- Result array: `res = []` |
| 38 | +- Index `i = 0` |
| 39 | +- New interval boundaries: `start = 4`, `end = 8` |
73 | 40 |
|
74 | | -```sh |
75 | | -intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] |
| 41 | +**2.2 Start Processing:** |
76 | 42 |
|
77 | | -Step 1: Add intervals before overlap |
78 | | -result = [[1,2]] (3,5 overlaps, so stop) |
| 43 | +We begin processing intervals from left to right, checking each interval's relationship with the new interval. |
79 | 44 |
|
80 | | -Step 2: Merge overlapping intervals |
81 | | -Overlap with [3,5]: newInterval = [min(4,3), max(8,5)] = [3,8] |
82 | | -Overlap with [6,7]: newInterval = [min(3,6), max(8,7)] = [3,8] |
83 | | -Overlap with [8,10]: newInterval = [min(3,8), max(8,10)] = [3,10] |
| 45 | +**2.3 Trace Walkthrough:** |
84 | 46 |
|
85 | | -Step 3: Add merged interval |
86 | | -result = [[1,2],[3,10]] |
| 47 | +| Step | i | Interval | Condition | Action | res | start, end | |
| 48 | +| ---- | - | -------- | --------- | ------ | --- | ---------- | |
| 49 | +| 1 | 0 | [1,2] | 2 < 4 (ends before) | Add to res | `[[1,2]]` | 4, 8 | |
| 50 | +| 2 | 1 | [3,5] | 3 <= 8 (overlaps) | Merge: start=min(4,3)=3, end=max(8,5)=8 | `[[1,2]]` | 3, 8 | |
| 51 | +| 3 | 2 | [6,7] | 6 <= 8 (overlaps) | Merge: start=min(3,6)=3, end=max(8,7)=8 | `[[1,2]]` | 3, 8 | |
| 52 | +| 4 | 3 | [8,10] | 8 <= 8 (overlaps) | Merge: start=min(3,8)=3, end=max(8,10)=10 | `[[1,2]]` | 3, 10 | |
| 53 | +| 5 | 4 | [12,16] | 12 > 10 (starts after) | Add merged [3,10], then add [12,16] | `[[1,2],[3,10],[12,16]]` | - | |
87 | 54 |
|
88 | | -Step 4: Add remaining intervals |
89 | | -result = [[1,2],[3,10],[12,16]] |
| 55 | +**2.4 Increment and Loop:** |
90 | 56 |
|
91 | | -Result: [[1,2],[3,10],[12,16]] |
92 | | -``` |
| 57 | +After processing each interval, we increment the index `i` and continue until all intervals are processed. |
93 | 58 |
|
94 | | -> **Note:** The key insight is to process intervals in three phases. This approach is efficient because we only need to traverse the array once, and we can determine which phase each interval belongs to by comparing its boundaries with the new interval. |
| 59 | +**2.5 Return Result:** |
95 | 60 |
|
96 | | -**Time Complexity:** O(n) - we visit each interval at most once |
97 | | -**Space Complexity:** O(n) - to store the result |
| 61 | +The result is `[[1,2],[3,10],[12,16]]`, where the new interval [4,8] has been merged with overlapping intervals [3,5], [6,7], and [8,10] to form [3,10]. |
0 commit comments