Back to all solutions

#3323 - Minimize Connected Groups by Inserting Interval

Problem Description

You are given a 2D array intervals, where intervals[i] = [starti, endi] represents the start and the end of interval i. You are also given an integer k.

You must add exactly one new interval [startnew, endnew] to the array such that:

  • The length of the new interval, endnew - startnew, is at most k.
  • After adding, the number of connected groups in intervals is minimized.

A connected group of intervals is a maximal collection of intervals that, when considered together, cover a continuous range from the smallest point to the largest point with no gaps between them. Here are some examples:

  • A group of intervals [[1, 2], [2, 5], [3, 3]] is connected because together they cover the range from 1 to 5 without any gaps.
  • However, a group of intervals [[1, 2], [3, 4]] is not connected because the segment (2, 3) is not covered.

Return the minimum number of connected groups after adding exactly one new interval to the array.

Solution

/**
 * @param {number[][]} intervals
 * @param {number} k
 * @return {number}
 */
var minConnectedGroups = function(intervals, k) {
  intervals.sort((a, b) => a[0] - b[0]);

  const groupStarts = [intervals[0][0]];
  const groupEnds = [intervals[0][1]];

  for (let i = 1; i < intervals.length; i++) {
    const [start, end] = intervals[i];

    if (start > groupEnds[groupEnds.length - 1]) {
      groupStarts.push(start);
      groupEnds.push(end);
    } else if (start <= groupEnds[groupEnds.length - 1] && groupEnds[groupEnds.length - 1] < end) {
      groupEnds[groupEnds.length - 1] = end;
    }
  }

  let maxGroupsToMerge = 0;
  for (let i = 0; i < groupEnds.length; i++) {
    const searchTarget = groupEnds[i] + k + 1;
    const rightmostIndex = binarySearchLeft(groupStarts, searchTarget) - 1;
    const groupsCanReach = rightmostIndex - i;
    maxGroupsToMerge = Math.max(maxGroupsToMerge, groupsCanReach);
  }

  return groupStarts.length - maxGroupsToMerge;

  function binarySearchLeft(arr, target) {
    let left = 0;
    let right = arr.length;

    while (left < right) {
      const mid = Math.floor((left + right) / 2);
      if (arr[mid] < target) {
        left = mid + 1;
      } else {
        right = mid;
      }
    }

    return left;
  }
};