Bird
Raised Fist0
Interview PrepintervalsmediumFacebookAmazonGoogleMicrosoftBloomberg

Merge Intervals

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
🎯
Merge Intervals
mediumINTERVALSFacebookAmazonGoogle

Imagine you have a calendar with multiple booked time slots, and you want to combine overlapping meetings to see your free time clearly.

💡 This problem is about combining overlapping intervals into one continuous interval. Beginners often struggle because they don't realize sorting the intervals by start time simplifies merging, and they try to compare every interval with every other, leading to inefficient solutions.
📋
Problem Statement

Given an array of intervals where intervals[i] = [start_i, end_i], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.

1 ≤ intervals.length ≤ 10^5intervals[i].length == 20 ≤ start_i ≤ end_i ≤ 10^9
💡
Example
Input"[[1,3],[2,6],[8,10],[15,18]]"
Output[[1,6],[8,10],[15,18]]

Intervals [1,3] and [2,6] overlap and are merged into [1,6]. The others do not overlap.

  • Single interval → output is the same single interval
  • All intervals non-overlapping → output is the same as input
  • All intervals overlapping → output is one merged interval
  • Intervals with same start and end points → merged correctly
⚠️
Common Mistakes
Not sorting intervals before merging

Incorrect merges or missed overlaps

Always sort intervals by start time before merging

Modifying the list while iterating without adjusting indices

Index errors or skipping intervals

Use careful index management or iterate backwards when removing elements

Not updating the end time correctly when merging

Merged intervals are incorrect or incomplete

Update the end time to the max of overlapping intervals

Returning the original intervals array without slicing after in-place merge

Extra intervals remain in output, causing wrong results

Return only the portion of the array up to the last merged index

🧠
Brute Force (Nested Loops Checking Overlaps)
💡 This approach exists to understand the problem deeply by checking every pair of intervals for overlap. It is inefficient but helps grasp the merging concept.

Intuition

Compare each interval with every other to check if they overlap, merge them if they do, and repeat until no more merges are possible.

Algorithm

  1. Initialize a list to hold merged intervals.
  2. For each interval, compare it with every other interval to check for overlap.
  3. If two intervals overlap, merge them into one interval.
  4. Repeat the process until no intervals can be merged further.
💡 This algorithm is hard to see as efficient because it involves repeated comparisons and merges, which can be confusing at first.
</>
Code
def merge(intervals):
    merged = []
    intervals = intervals[:]  # copy to avoid modifying input
    while intervals:
        current = intervals.pop(0)
        i = 0
        while i < len(intervals):
            if current[1] >= intervals[i][0] and intervals[i][1] >= current[0]:
                current = [min(current[0], intervals[i][0]), max(current[1], intervals[i][1])]
                intervals.pop(i)
            else:
                i += 1
        merged.append(current)
    return merged

# Driver code
if __name__ == '__main__':
    intervals = [[1,3],[2,6],[8,10],[15,18]]
    print(merge(intervals))
Line Notes
merged = []Initialize list to store merged intervals to accumulate results.
intervals = intervals[:] # copy to avoid modifying inputCopy input to avoid side effects on original data.
while intervals:Process intervals until all have been merged and removed.
current = intervals.pop(0)Pick the first interval to compare and merge with others.
while i < len(intervals):Iterate over remaining intervals to check for overlaps.
if current[1] >= intervals[i][0] and intervals[i][1] >= current[0]:Check if current interval overlaps with intervals[i].
current = [min(current[0], intervals[i][0]), max(current[1], intervals[i][1])]Merge overlapping intervals by updating start and end.
intervals.pop(i)Remove merged interval to avoid reprocessing it.
else: i += 1Move to next interval if no overlap found.
merged.append(current)Add the fully merged interval to the result list.
import java.util.*;
public class MergeIntervals {
    public static List<int[]> merge(int[][] intervals) {
        List<int[]> merged = new ArrayList<>();
        List<int[]> list = new ArrayList<>(Arrays.asList(intervals));
        while (!list.isEmpty()) {
            int[] current = list.remove(0);
            int i = 0;
            while (i < list.size()) {
                int[] interval = list.get(i);
                if (current[1] >= interval[0] && interval[1] >= current[0]) {
                    current[0] = Math.min(current[0], interval[0]);
                    current[1] = Math.max(current[1], interval[1]);
                    list.remove(i);
                } else {
                    i++;
                }
            }
            merged.add(current);
        }
        return merged;
    }
    public static void main(String[] args) {
        int[][] intervals = {{1,3},{2,6},{8,10},{15,18}};
        List<int[]> result = merge(intervals);
        for (int[] interval : result) {
            System.out.println("[" + interval[0] + "," + interval[1] + "]");
        }
    }
}
Line Notes
List<int[]> merged = new ArrayList<>();Initialize list to store merged intervals.
List<int[]> list = new ArrayList<>(Arrays.asList(intervals));Copy input array to a modifiable list.
while (!list.isEmpty()) {Process intervals until all are merged and removed.
int[] current = list.remove(0);Pick first interval to compare and merge.
while (i < list.size()) {Iterate over remaining intervals to check for overlaps.
if (current[1] >= interval[0] && interval[1] >= current[0]) {Check if intervals overlap.
current[0] = Math.min(current[0], interval[0]);Update start of merged interval.
current[1] = Math.max(current[1], interval[1]);Update end of merged interval.
list.remove(i);Remove merged interval to avoid reprocessing.
else { i++; }Move to next interval if no overlap.
merged.add(current);Add merged interval to result list.
#include <iostream>
#include <vector>
using namespace std;

vector<vector<int>> merge(vector<vector<int>>& intervals) {
    vector<vector<int>> merged;
    vector<vector<int>> list = intervals;
    while (!list.empty()) {
        vector<int> current = list[0];
        list.erase(list.begin());
        for (int i = 0; i < (int)list.size();) {
            if (current[1] >= list[i][0] && list[i][1] >= current[0]) {
                current[0] = min(current[0], list[i][0]);
                current[1] = max(current[1], list[i][1]);
                list.erase(list.begin() + i);
            } else {
                i++;
            }
        }
        merged.push_back(current);
    }
    return merged;
}

int main() {
    vector<vector<int>> intervals = {{1,3},{2,6},{8,10},{15,18}};
    vector<vector<int>> result = merge(intervals);
    for (auto &interval : result) {
        cout << "[" << interval[0] << "," << interval[1] << "]\n";
    }
    return 0;
}
Line Notes
vector<vector<int>> merged;Initialize vector to store merged intervals.
vector<vector<int>> list = intervals;Copy input intervals for modification.
while (!list.empty()) {Process intervals until all merged.
vector<int> current = list[0];Pick first interval to compare and merge.
list.erase(list.begin());Remove picked interval from list.
for (int i = 0; i < (int)list.size();) {Iterate over remaining intervals.
if (current[1] >= list[i][0] && list[i][1] >= current[0]) {Check if intervals overlap.
current[0] = min(current[0], list[i][0]);Update start of merged interval.
current[1] = max(current[1], list[i][1]);Update end of merged interval.
list.erase(list.begin() + i);Remove merged interval to avoid reprocessing.
else { i++; }Move to next interval if no overlap.
merged.push_back(current);Add merged interval to result.
function merge(intervals) {
    let merged = [];
    intervals = intervals.slice();
    while (intervals.length > 0) {
        let current = intervals.shift();
        let i = 0;
        while (i < intervals.length) {
            if (current[1] >= intervals[i][0] && intervals[i][1] >= current[0]) {
                current = [Math.min(current[0], intervals[i][0]), Math.max(current[1], intervals[i][1])];
                intervals.splice(i, 1);
            } else {
                i++;
            }
        }
        merged.push(current);
    }
    return merged;
}

// Driver code
console.log(merge([[1,3],[2,6],[8,10],[15,18]]));
Line Notes
let merged = [];Initialize array to store merged intervals.
intervals = intervals.slice();Copy input to avoid mutating original array.
while (intervals.length > 0) {Process intervals until all merged.
let current = intervals.shift();Pick first interval to compare and merge.
while (i < intervals.length) {Iterate over remaining intervals.
if (current[1] >= intervals[i][0] && intervals[i][1] >= current[0]) {Check if intervals overlap.
current = [Math.min(current[0], intervals[i][0]), Math.max(current[1], intervals[i][1])];Merge overlapping intervals.
intervals.splice(i, 1);Remove merged interval to avoid reprocessing.
else { i++; }Move to next interval if no overlap.
merged.push(current);Add merged interval to result.
Complexity
TimeO(n^2)
SpaceO(n)

Each interval is compared with every other interval, leading to quadratic time. Space is linear for the output.

💡 For n=20 intervals, this means up to 400 comparisons, which is inefficient for large inputs.
Interview Verdict: TLE / Use only to introduce

This approach is too slow for large inputs but helps demonstrate understanding of the problem before optimizing.

🧠
Sorting + One Pass Merge
💡 Sorting intervals by start time allows merging in a single pass, which is much more efficient and easier to implement once understood.

Intuition

Sort intervals by start time, then iterate through them, merging overlapping intervals by comparing current interval start with last merged interval end.

Algorithm

  1. Sort intervals by their start time.
  2. Initialize merged list with the first interval.
  3. Iterate over remaining intervals:
  4. If current interval overlaps with last merged, merge them by updating the end.
  5. Else, add current interval to merged list.
💡 Sorting simplifies the problem by ensuring intervals are processed in order, making it easier to detect overlaps.
</>
Code
def merge(intervals):
    if not intervals:
        return []
    intervals.sort(key=lambda x: x[0])
    merged = [intervals[0]]
    for current in intervals[1:]:
        last = merged[-1]
        if current[0] <= last[1]:
            last[1] = max(last[1], current[1])
        else:
            merged.append(current)
    return merged

# Driver code
if __name__ == '__main__':
    intervals = [[1,3],[2,6],[8,10],[15,18]]
    print(merge(intervals))
Line Notes
if not intervals:Handle empty input edge case to avoid errors.
intervals.sort(key=lambda x: x[0])Sort intervals by start time to process in order.
merged = [intervals[0]]Initialize merged list with first interval as starting point.
for current in intervals[1:]:Iterate over remaining intervals to merge.
last = merged[-1]Get last merged interval to compare with current.
if current[0] <= last[1]:Check if current interval overlaps with last merged.
last[1] = max(last[1], current[1])Merge intervals by updating end time.
else: merged.append(current)No overlap, add current interval to merged list.
import java.util.*;
public class MergeIntervals {
    public static List<int[]> merge(int[][] intervals) {
        if (intervals.length == 0) return new ArrayList<>();
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
        List<int[]> merged = new ArrayList<>();
        merged.add(intervals[0]);
        for (int i = 1; i < intervals.length; i++) {
            int[] last = merged.get(merged.size() - 1);
            if (intervals[i][0] <= last[1]) {
                last[1] = Math.max(last[1], intervals[i][1]);
            } else {
                merged.add(intervals[i]);
            }
        }
        return merged;
    }
    public static void main(String[] args) {
        int[][] intervals = {{1,3},{2,6},{8,10},{15,18}};
        List<int[]> result = merge(intervals);
        for (int[] interval : result) {
            System.out.println("[" + interval[0] + "," + interval[1] + "]");
        }
    }
}
Line Notes
if (intervals.length == 0) return new ArrayList<>();Handle empty input to avoid errors.
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));Sort intervals by start time for ordered processing.
List<int[]> merged = new ArrayList<>();Initialize list to store merged intervals.
merged.add(intervals[0]);Add first interval as starting merged interval.
for (int i = 1; i < intervals.length; i++) {Iterate over remaining intervals.
int[] last = merged.get(merged.size() - 1);Get last merged interval for comparison.
if (intervals[i][0] <= last[1]) {Check if current interval overlaps with last merged.
last[1] = Math.max(last[1], intervals[i][1]);Merge intervals by updating end time.
else { merged.add(intervals[i]); }No overlap, add current interval to merged list.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<vector<int>> merge(vector<vector<int>>& intervals) {
    if (intervals.empty()) return {};
    sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b) {
        return a[0] < b[0];
    });
    vector<vector<int>> merged;
    merged.push_back(intervals[0]);
    for (int i = 1; i < (int)intervals.size(); i++) {
        if (intervals[i][0] <= merged.back()[1]) {
            merged.back()[1] = max(merged.back()[1], intervals[i][1]);
        } else {
            merged.push_back(intervals[i]);
        }
    }
    return merged;
}

int main() {
    vector<vector<int>> intervals = {{1,3},{2,6},{8,10},{15,18}};
    vector<vector<int>> result = merge(intervals);
    for (auto &interval : result) {
        cout << "[" << interval[0] << "," << interval[1] << "]\n";
    }
    return 0;
}
Line Notes
if (intervals.empty()) return {};Handle empty input to avoid errors.
sort(intervals.begin(), intervals.end(), ...Sort intervals by start time for ordered processing.
vector<vector<int>> merged;Initialize vector to store merged intervals.
merged.push_back(intervals[0]);Add first interval as starting merged interval.
for (int i = 1; i < (int)intervals.size(); i++) {Iterate over remaining intervals.
if (intervals[i][0] <= merged.back()[1]) {Check if current interval overlaps with last merged.
merged.back()[1] = max(merged.back()[1], intervals[i][1]);Merge intervals by updating end time.
else { merged.push_back(intervals[i]); }No overlap, add current interval to merged list.
function merge(intervals) {
    if (intervals.length === 0) return [];
    intervals.sort((a, b) => a[0] - b[0]);
    const merged = [intervals[0]];
    for (let i = 1; i < intervals.length; i++) {
        let last = merged[merged.length - 1];
        if (intervals[i][0] <= last[1]) {
            last[1] = Math.max(last[1], intervals[i][1]);
        } else {
            merged.push(intervals[i]);
        }
    }
    return merged;
}

// Driver code
console.log(merge([[1,3],[2,6],[8,10],[15,18]]));
Line Notes
if (intervals.length === 0) return [];Handle empty input to avoid errors.
intervals.sort((a, b) => a[0] - b[0]);Sort intervals by start time for ordered processing.
const merged = [intervals[0]];Initialize merged list with first interval.
for (let i = 1; i < intervals.length; i++) {Iterate over remaining intervals.
let last = merged[merged.length - 1];Get last merged interval for comparison.
if (intervals[i][0] <= last[1]) {Check if current interval overlaps with last merged.
last[1] = Math.max(last[1], intervals[i][1]);Merge intervals by updating end time.
else { merged.push(intervals[i]); }No overlap, add current interval to merged list.
Complexity
TimeO(n log n)
SpaceO(n)

Sorting takes O(n log n), and merging in one pass is O(n). Space is for output and sorting.

💡 For n=1000 intervals, sorting is about 10,000 operations, and merging is 1000 operations, efficient for large inputs.
Interview Verdict: Accepted / Optimal for most cases

This approach is efficient and commonly expected in interviews for merging intervals.

🧠
In-place Merge After Sorting
💡 This approach optimizes space by merging intervals in-place after sorting, reducing extra memory usage.

Intuition

Sort intervals by start time, then overwrite intervals array by merging overlapping intervals as you iterate, keeping track of the position to write merged intervals.

Algorithm

  1. Sort intervals by start time.
  2. Initialize a pointer to track position of last merged interval.
  3. Iterate over intervals starting from second interval:
  4. If current overlaps with last merged, merge by updating end.
  5. Else, move pointer forward and copy current interval.
💡 This approach is tricky because it modifies the input array directly, requiring careful pointer management.
</>
Code
def merge(intervals):
    if not intervals:
        return []
    intervals.sort(key=lambda x: x[0])
    index = 0
    for i in range(1, len(intervals)):
        if intervals[i][0] <= intervals[index][1]:
            intervals[index][1] = max(intervals[index][1], intervals[i][1])
        else:
            index += 1
            intervals[index] = intervals[i]
    return intervals[:index+1]

# Driver code
if __name__ == '__main__':
    intervals = [[1,3],[2,6],[8,10],[15,18]]
    print(merge(intervals))
Line Notes
if not intervals:Handle empty input to avoid errors.
intervals.sort(key=lambda x: x[0])Sort intervals by start time for ordered processing.
index = 0Pointer to track last merged interval position.
for i in range(1, len(intervals))Iterate over intervals starting from second.
if intervals[i][0] <= intervals[index][1]:Check if current interval overlaps with last merged.
intervals[index][1] = max(intervals[index][1], intervals[i][1])Merge intervals in-place by updating end.
else: index += 1Move pointer forward for new non-overlapping interval.
intervals[index] = intervals[i]Copy current interval to merged position.
return intervals[:index+1]Return merged intervals slice up to last merged index.
import java.util.*;
public class MergeIntervals {
    public static int[][] merge(int[][] intervals) {
        if (intervals.length == 0) return new int[0][0];
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
        int index = 0;
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i][0] <= intervals[index][1]) {
                intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);
            } else {
                index++;
                intervals[index] = intervals[i];
            }
        }
        return Arrays.copyOfRange(intervals, 0, index + 1);
    }
    public static void main(String[] args) {
        int[][] intervals = {{1,3},{2,6},{8,10},{15,18}};
        int[][] result = merge(intervals);
        for (int[] interval : result) {
            System.out.println("[" + interval[0] + "," + interval[1] + "]");
        }
    }
}
Line Notes
if (intervals.length == 0) return new int[0][0];Handle empty input to avoid errors.
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));Sort intervals by start time for ordered processing.
int index = 0;Pointer to track last merged interval position.
for (int i = 1; i < intervals.length; i++) {Iterate over intervals starting from second.
if (intervals[i][0] <= intervals[index][1]) {Check if current interval overlaps with last merged.
intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);Merge intervals in-place by updating end.
else { index++; intervals[index] = intervals[i]; }Move pointer and copy new interval.
return Arrays.copyOfRange(intervals, 0, index + 1);Return merged intervals slice.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<vector<int>> merge(vector<vector<int>>& intervals) {
    if (intervals.empty()) return {};
    sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b) {
        return a[0] < b[0];
    });
    int index = 0;
    for (int i = 1; i < (int)intervals.size(); i++) {
        if (intervals[i][0] <= intervals[index][1]) {
            intervals[index][1] = max(intervals[index][1], intervals[i][1]);
        } else {
            index++;
            intervals[index] = intervals[i];
        }
    }
    intervals.resize(index + 1);
    return intervals;
}

int main() {
    vector<vector<int>> intervals = {{1,3},{2,6},{8,10},{15,18}};
    vector<vector<int>> result = merge(intervals);
    for (auto &interval : result) {
        cout << "[" << interval[0] << "," << interval[1] << "]\n";
    }
    return 0;
}
Line Notes
if (intervals.empty()) return {};Handle empty input to avoid errors.
sort(intervals.begin(), intervals.end(), ...Sort intervals by start time for ordered processing.
int index = 0;Pointer to track last merged interval position.
for (int i = 1; i < (int)intervals.size(); i++) {Iterate over intervals starting from second.
if (intervals[i][0] <= intervals[index][1]) {Check if current interval overlaps with last merged.
intervals[index][1] = max(intervals[index][1], intervals[i][1]);Merge intervals in-place by updating end.
else { index++; intervals[index] = intervals[i]; }Move pointer and copy new interval.
intervals.resize(index + 1);Resize vector to keep only merged intervals.
function merge(intervals) {
    if (intervals.length === 0) return [];
    intervals.sort((a, b) => a[0] - b[0]);
    let index = 0;
    for (let i = 1; i < intervals.length; i++) {
        if (intervals[i][0] <= intervals[index][1]) {
            intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);
        } else {
            index++;
            intervals[index] = intervals[i];
        }
    }
    return intervals.slice(0, index + 1);
}

// Driver code
console.log(merge([[1,3],[2,6],[8,10],[15,18]]));
Line Notes
if (intervals.length === 0) return [];Handle empty input to avoid errors.
intervals.sort((a, b) => a[0] - b[0]);Sort intervals by start time for ordered processing.
let index = 0;Pointer to track last merged interval position.
for (let i = 1; i < intervals.length; i++) {Iterate over intervals starting from second.
if (intervals[i][0] <= intervals[index][1]) {Check if current interval overlaps with last merged.
intervals[index][1] = Math.max(intervals[index][1], intervals[i][1]);Merge intervals in-place by updating end.
else { index++; intervals[index] = intervals[i]; }Move pointer and copy new interval.
return intervals.slice(0, index + 1);Return merged intervals slice.
Complexity
TimeO(n log n)
SpaceO(1) additional space

Sorting is O(n log n), merging is O(n). Space is optimized by modifying input in-place.

💡 For large n, this saves memory compared to creating new lists, important in memory-constrained environments.
Interview Verdict: Accepted / Space optimized

This approach is ideal when interviewers ask for in-place or space-efficient solutions.

📊
All Approaches - One-Glance Tradeoffs
💡 Use the sorting + one pass merge approach in 95% of interviews unless space optimization is explicitly requested.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute ForceO(n^2)O(n)NoN/AMention only - never code
2. Sorting + One Pass MergeO(n log n)O(n)NoN/ACode this approach
3. In-place Merge After SortingO(n log n)O(1) additionalNoN/ACode if asked for space optimization
💼
Interview Strategy
💡 Use this guide to understand the problem deeply, practice coding all approaches, and prepare to explain tradeoffs clearly in interviews.

How to Present

Step 1: Clarify the problem and constraints with the interviewer.Step 2: Describe the brute force approach to show understanding.Step 3: Explain the sorting + one pass merge approach as the optimal solution.Step 4: If asked, discuss space optimization with in-place merging.Step 5: Code the chosen approach carefully, test with examples and edge cases.

Time Allocation

Clarify: 2min → Approach: 3min → Code: 10min → Test: 5min. Total ~20min

What the Interviewer Tests

The interviewer tests your ability to recognize sorting as key, handle edge cases, write clean code, and optimize space/time.

Common Follow-ups

  • How to insert a new interval and merge? → Modify merge to handle insertion.
  • Can you do this without sorting? → Generally no, sorting is essential.
💡 These follow-ups test your ability to adapt the merge logic and understand the necessity of sorting.
🔍
Pattern Recognition

When to Use

1) Input is a list of intervals, 2) Need to combine overlapping intervals, 3) Output must be non-overlapping intervals, 4) Sorting by start time is possible.

Signature Phrases

merge overlapping intervalscombine intervalsnon-overlapping intervals

NOT This Pattern When

Problems involving intervals but requiring different techniques like interval scheduling or DP.

Similar Problems

Insert Interval - similar merging logic with insertionNon-overlapping Intervals - counting intervals after mergesMeeting Rooms - scheduling overlaps

Practice

(1/5)
1. Consider the following Python code implementing the optimal car pooling solution. What is the return value when called with trips = [[2,1,5],[3,3,7]] and capacity = 4?
def carPooling(trips, capacity):
    max_location = 0
    for _, start, end in trips:
        max_location = max(max_location, end)
    diff = [0] * (max_location + 1)
    for num, start, end in trips:
        diff[start] += num
        diff[end] -= num
    current_passengers = 0
    for i in range(max_location + 1):
        current_passengers += diff[i]
        if current_passengers > capacity:
            return false
    return true

print(carPooling([[2,1,5],[3,3,7]], 4))
easy
A. Error due to index out of range
B. true
C. false
D. true only if capacity is at least 5

Solution

  1. Step 1: Build difference array

    diff after processing trips: diff[1]+=2, diff[5]-=2, diff[3]+=3, diff[7]-=3
  2. Step 2: Sweep through diff to track passengers

    At location 1: current_passengers=2; at 3: current_passengers=5 (2+3), which exceeds capacity=4 -> return false
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Passenger count exceeds capacity at location 3 [OK]
Hint: Sum diffs to track passengers, check capacity [OK]
Common Mistakes:
  • Off-by-one in diff array indexing
  • Checking capacity only at trip start
  • Forgetting to decrement at trip end
2. Consider the following Python function that finds the minimum number of arrows to burst balloons represented as intervals. Given the input points = [[10,16],[2,8],[1,6],[7,12]], what is the value of arrows after processing all intervals?
easy
A. 1
B. 4
C. 3
D. 2

Solution

  1. Step 1: Sort intervals by end coordinate

    Sorted points: [[1,6],[2,8],[7,12],[10,16]]
  2. Step 2: Iterate and count arrows

    Start with arrow_pos=6, arrows=1. Next interval start=2 ≤ 6 (covered), next start=7 > 6 (new arrow), arrows=2, arrow_pos=12. Next start=10 ≤ 12 (covered).
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Two arrows suffice to burst all balloons [OK]
Hint: Sort by end, count arrows when start > current arrow position [OK]
Common Mistakes:
  • Not sorting intervals before processing
  • Using start >= arrow_pos instead of start > arrow_pos
  • Off-by-one errors in counting arrows
3. You are given a list of intervals where each interval has a start and end time. Your goal is to select the maximum number of intervals such that none of the selected intervals overlap. Which algorithmic approach guarantees an optimal solution for this problem?
easy
A. Dynamic programming that tries all subsets of intervals to find the maximum non-overlapping set.
B. Sort intervals by their start time and always pick the earliest starting interval first.
C. Sort intervals by their end time and greedily select intervals that start after the last selected interval ends.
D. Use a graph coloring algorithm to assign intervals to different colors ensuring no overlaps.

Solution

  1. Step 1: Understand the problem goal

    The problem requires selecting the maximum number of intervals with no overlaps.
  2. Step 2: Identify the optimal greedy strategy

    Sorting intervals by their end time and greedily picking intervals that start after the last selected interval ends ensures the maximum number of intervals are chosen.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Greedy by earliest end time is a classic optimal approach [OK]
Hint: Sort by end time for max non-overlapping intervals [OK]
Common Mistakes:
  • Sorting by start time and picking earliest start first
  • Trying brute force DP without pruning
  • Using graph coloring which is unrelated here
4. You are given a list of intervals and need to remove all intervals that are covered by another interval. Which approach guarantees an optimal solution with O(n log n) time complexity and O(1) extra space besides the input?
easy
A. Use a brute force nested loop to check coverage between every pair of intervals.
B. Sort intervals by start ascending and end descending, then scan once to count uncovered intervals.
C. Use dynamic programming to find the maximum set of non-covered intervals.
D. Sort intervals by end ascending and greedily pick intervals that do not overlap.

Solution

  1. Step 1: Understand sorting criteria

    Sorting intervals by start ascending and end descending ensures intervals with the same start are ordered from longest to shortest, so coverage can be detected in one pass.
  2. Step 2: Single pass coverage check

    By scanning intervals in sorted order and tracking the maximum end seen, we can count intervals that are not covered by any previous interval.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Sorting by start ascending and end descending enables O(n log n) sorting plus O(n) scanning [OK]
Hint: Sort by start asc, end desc, then scan once [OK]
Common Mistakes:
  • Sorting only by start ascending misses coverage when starts equal
  • Using nested loops causes TLE on large inputs
5. Consider this buggy code snippet for removing covered intervals:
def remove_covered_intervals(intervals):
    intervals.sort(key=lambda x: (x[0], x[1]))  # Bug here
    count = 0
    max_end = 0
    for _, end in intervals:
        if end > max_end:
            count += 1
            max_end = end
    return count
What is the bug in this code?
medium
A. The condition 'if end > max_end' should be 'if end >= max_end' to include equal ends.
B. max_end is not updated correctly inside the loop.
C. Sorting by end ascending instead of descending causes coverage detection failure.
D. The nested loop for coverage check is missing, causing incorrect results.

Solution

  1. Step 1: Analyze sorting key

    Sorting by (start ascending, end ascending) orders intervals with same start from shortest to longest, which breaks coverage detection.
  2. Step 2: Understand coverage detection logic

    Coverage detection relies on intervals with same start being sorted longest first (end descending) so covered intervals come after.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Sorting end ascending causes missed coverage when starts equal [OK]
Hint: Sort end descending to detect coverage correctly [OK]
Common Mistakes:
  • Sorting end ascending instead of descending
  • Using strict inequality incorrectly