problemmediumalgorithmsmerge-overlapping-intervals-on-insertmerge overlapping intervals on insertmergeoverlappingintervalsoninsertinterviewbit-merge-intervalsinterviewbit merge intervalsinterviewbitmergeintervalsleetcode-57leetcode 57leetcode57

Insert Interval

MediumUpdated: Nov 24, 2025
Practice on:
Video Solutions:

Problem

Given a set of non-overlapping & sorted intervals by start time, insert a new interval into the intervals (merge if necessary).

OR

You are given an array of non-overlapping intervals intervals where intervals[i] = [starti, endi] represent the start and the end of the ith interval and intervals is sorted in ascending order by starti. You are also given an interval newInterval = [start, end] that represents the start and end of another interval.

Insert newInterval into intervals such that intervals is still sorted in ascending order by starti and intervals still does not have any overlapping intervals (merge overlapping intervals if necessary).

Return intervals after the insertion.

Examples

Example 1:

Input: intervals = [[1,3],[6,9]], newInterval = [2,5] y
Output: [[1,5],[6,9]]%%  %%

Example 2:

Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
Output: [[1,2],[3,10],[12,16]]
Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].

Solution

Video explanation

Here is the video explaining this method in detail. Please check it out:

<div class="youtube-embed"><iframe src="https://www.youtube.com/embed/4apizj9b3Pw" frameborder="0" allowfullscreen></iframe></div>

Method 1 - Naive

The most straightforward way to solve this is to ignore the fact that the initial list is sorted. We can treat this problem as simply "merging a list of unsorted overlapping intervals". We have covered this problem here - [Merge Overlapping Intervals](merge-overlapping-intervals). The core idea is to add our new interval to the list and then use a standard merging algorithm. A standard merging algorithm requires the intervals to be sorted by their start times to work correctly.

Complexity

  • ⏰ Time complexity: O(n log n). Dominated by the sorting step.
  • 🧺 Space complexity: O(n). To store the merged list.

Method 1 - Greedy with 3 loops

If the list was not sorted, we could have appended the newInterval to the end of list. And then the problem was [Merge Overlapping Intervals](merge-overlapping-intervals).

But, given that the intervals are sorted, our task simplifies to finding the correct index where the newInterval can be placed. By We can iterate through given intervals list, and we encounter three scenarios:

  • Before New Interval (newInterval.end <interval.start): If the end of newInterval is before the start of the current interval, we insert newInterval into the list at this position.
  • After New Interval (newInterval.start > interval.end): If the start of newInterval is after the end of the current interval, we skip these intervals and eventually insert newInterval after the current interval.
  • Overlapping Intervals: When there is an overlap, we merge newInterval with the current interval. The merged interval will have: c.start=min(newInterval.start, interval.start) and c.end=max(newInterval.end, interval.end)

Here is the visual view of how the 3 cases will look. Whenever there is intersection, created a new interval.

insert-interval-cases.excalidraw

Code

Java
class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        List<int[]> result = new ArrayList<>();
        int i = 0;
        int n = intervals.length;

        // Case 1: Add all intervals that come before newInterval and don't overlap
        while (i < n && intervals[i][1] < newInterval[0]) {
            result.add(intervals[i]);
            i++;
        }

        // Case 2: Merge newInterval with all overlapping intervals
        while (i < n && intervals[i][0] <= newInterval[1]) {
            newInterval[0] = Math.min(newInterval[0], intervals[i][0]);
            newInterval[1] = Math.max(newInterval[1], intervals[i][1]);
            i++;
        }
        result.add(newInterval); // Add the merged newInterval

        // Case 3: Add all intervals that come after newInterval and don't overlap
        while (i < n) {
            result.add(intervals[i]);
            i++;
        }

        return result.toArray(new int[result.size()][]);
    }
}
Python
class Solution:
    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
        result = []
        i = 0
        n = len(intervals)

        # Case 1: Add all intervals that come before newInterval and don't overlap
        while i < n and intervals[i][1] < newInterval[0]:
            result.append(intervals[i])
            i += 1

        # Case 2: Merge newInterval with all overlapping intervals
        while i < n and intervals[i][0] <= newInterval[1]:
            newInterval[0] = min(newInterval[0], intervals[i][0])
            newInterval[1] = max(newInterval[1], intervals[i][1])
            i += 1
        result.append(newInterval)  # Add the merged newInterval

        # Case 3: Add all intervals that come after newInterval and don't overlap
        while i < n:
            result.append(intervals[i])
            i += 1

        return result

Complexity

  • ⏰ Time complexity: O(n), as we iterate through the list only once.
  • 🧺 Space complexity: O(n), to store the result list.

Method 3 - Greedy with 1 loop

This is similar to previous approach, just doing everything in one loop.

Code

Java
Interval Array
class Solution {
	public int[][] insert(int[][] intervals, int[] newInterval) {
		List<int[]> ans = new LinkedList<>();
		for(int[] interval: intervals){
			if(interval[1] < newInterval[0]){
				ans.add(interval);
			}else if(interval[0] > newInterval[1]){
				ans.add(newInterval);
				newInterval = interval;
			}else if(interval[1] >= newInterval[0] || interval[0] <= newInterval[1]){
				int start = Math.min(interval[0], newInterval[0]);
				int end = Math.max(interval[1], newInterval[1]);
				newInterval = new int[]{start, end};
			}
		}
	
		ans.add(newInterval);
		return ans.toArray(int[][]::new);
	}
}    
Interval Object
class Solution {
	public List<Interval> insert(List<Interval> intervals, Interval newInterval) {
	
		List<Interval> ans = new ArrayList<Interval> ();
	
		for (Interval interval: intervals) {
			if (interval.end<newInterval.start) {
				ans.add(interval);
			} else if (interval.start > newInterval.end) {
				ans.add(newInterval);
				newInterval = interval;
			} else if (interval.end >= newInterval.start || interval.start<= newInterval.end) {
				newInterval = new Interval(Math.min(interval.start, newInterval.start), Math.max(newInterval.end, interval.end));
			}
		}
		
		ans.add(newInterval);
	
		return ans;
	}
}
Python
class Solution:
    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
        result = []
        
        for interval in intervals:
            # Case 1: current interval is after newInterval
            # We need to add the newInterval and then update it to the current interval
            if interval[1] < newInterval[0]:
                result.append(newInterval)
                newInterval = interval
            # Case 2: current interval is before newInterval
            elif interval[0] > newInterval[1]:
                result.append(interval)
            # Case 3: Overlap
            else:
                newInterval[0] = min(interval[0], newInterval[0])
                newInterval[1] = max(interval[1], newInterval[1])
                
        result.append(newInterval) # Add the final merged newInterval
        
        return result
Rust
impl Solution {
    pub fn insert(intervals: Vec<Vec<i32>>, new_interval: Vec<i32>) -> Vec<Vec<i32>> {
        use std::cmp::{min, max};

        let mut ans = vec![];
        let mut new_interval = new_interval;

        for interval in intervals {
            if interval[1] < new_interval[0] {
                ans.push(interval);
            }else if interval[0] > new_interval[1] {
                ans.push(new_interval);
                new_interval = interval;
            }else {
                let start = min(interval[0], new_interval[0]);
                let end = max(interval[1], new_interval[1]);
                new_interval = vec![start, end];
            }

        }
        ans.push(new_interval);
        ans
    }
}

Complexity

  • ⏰ Time complexity: O(n), as we iterate through the list only once.
  • 🧺 Space complexity: O(n), to store the result list.

Comments