Open In App

Find the minimum range size that contains the given element for Q queries

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array Intervals[] consisting of N pairs of integers where each pair is denoting the value range [L, R]. Also, given an integer array Q[] consisting of M queries. For each query, the task is to find the size of the smallest range that contains that element. Return -1 if no valid interval exists.

Examples

Input: Intervals[] = [[1, 4], [2, 3], [3, 6], [9, 25], [7, 15], [4, 4]]
           Q[] = [7, 50, 2]
Output: [9, -1, 2]
Explanation: Element 7 is in the range [7, 15] only therefore, the answer will be 15 – 7 + 1 = 9. Element 50 is in no range. Therefore, the answer will be -1.
Similarly, element 2 is in the range [2, 3] and [1, 4] but the smallest range is [2, 3] therefore, the answer will be 3-2+1 = 2.

Input: Intervals[] = [[1, 4], [2, 4], [3, 6]]
           Q[] = [2, 3]
Output: [3, 3]
 

Naive Approach: The simplest approach to solve the problem is to Iterate through the array range[] and for each query find the smallest range that contains the given elements.

Time Complexity: O(N×M)
Auxiliary Space: O(M)

Efficient Approach: The approach mentioned above can be optimized further by using priority_queue. Follow the steps below to solve the problem:

  • Initialize a vector of vectors, say Queries and insert all the queries in the array Q along with its index.
  • Sort the vector Intervals and Queries using the default sorting function of the vector.
  • Initialize a priority_queue, say pq with key as the size of Interval and value as right bound of the range.
  • Initialize a vector, say result that will store the size of minimum range for each query.
  • Initialize an integer variable, say i that will keep the track of traversed elements of the array Intervals.
  • Iterate in the range [0, M-1] using the variable j and perform the following steps:
    • Iterate while i < Intervals.size() and Intervals[i][0] <= Queries[j][0], insert -(Intervals[i][1] – Intervals[i][0] + 1), Intervals[i][1] as pair and increment the value of i by 1.
    • Now remove all the elements from the priority_queue pq with the right element less than Queries[j][0].
    • If the size of priority_queue pq>0, then modify the value of result[Queries[j][1]] as pq.top()[0].
  • Return the array res[] as the answer.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the size of minimum
// Interval that contains the given element
vector<int> minInterval(vector<vector<int> >& intervals,
                        vector<int>& q)
{
    // Store all the queries
    // along with their index
    vector<vector<int> > queries;
 
    for (int i = 0; i < q.size(); i++)
        queries.push_back({ q[i], i });
 
    // Sort the vector intervals and queries
    sort(intervals.begin(), intervals.end());
    sort(queries.begin(), queries.end());
 
    // Max priority queue to keep track
    // of intervals size and right value
    priority_queue<vector<int> > pq;
 
    // Stores the result of all the queries
    vector<int> result(queries.size(), -1);
 
    // Current position of intervals
    int i = 0;
 
    for (int j = 0; j < queries.size(); j++) {
 
        // Stores the current query
        int temp = queries[j][0];
 
        // Insert all the intervals whose left value
        // is less than or equal to the current query
        while (i < intervals.size()
               && intervals[i][0] <= temp) {
 
            // Insert the negative of range size and
            // the right bound of the interval
            pq.push(
                { -intervals[i][1] + intervals[i][0] - 1,
                  intervals[i++][1] });
        }
 
        // Pop all the intervals with right value
        // less than the current query
        while (!pq.empty() && temp > pq.top()[1]) {
            pq.pop();
        }
 
        // Check if the valid interval exists
        // Update the answer for current query
        // in result array
        if (!pq.empty())
            result[queries[j][1]] = -pq.top()[0];
    }
    // Return the result array
    return result;
}
 
// Driver Code
int main()
{
    // Given Input
    vector<vector<int> > intervals
        = { { 1, 4 }, { 2, 3 }, { 3, 6 }, { 9, 25 }, { 7, 15 }, { 4, 4 } };
    vector<int> Q = { 7, 50, 2, 3, 4, 9 };
 
    // Function Call
    vector<int> result = minInterval(intervals, Q);
 
    // Print the result for each query
    for (int i = 0; i < result.size(); i++)
        cout << result[i] << " ";
    return 0;
}


Java




import java.util.*;
class Main
{
   
  // Function to find the size of minimum
  // Interval that contains the given element
  public static int[] minInterval(int[][] intervals,
                                  int[] q)
  {
     
    // Store all the queries
    // along with their index
    int[][] queries = new int[q.length][2];
 
    for (int i = 0; i < q.length; i++) {
      queries[i][0] = q[i];
      queries[i][1] = i;
    }
 
    // Sort the array intervals and queries
    Arrays.sort(intervals, (a, b) -> {
      if (a[0] == b[0])
        return a[1] - b[1];
      return a[0] - b[0];
    });
    Arrays.sort(queries, (a, b) -> {
      if (a[0] == b[0])
        return a[1] - b[1];
      return a[0] - b[0];
    });
 
    // Max priority queue to keep track
    // of intervals size and right value
    PriorityQueue<int[]> pq
      = new PriorityQueue<>((a, b) -> {
        if (a[0] == b[0])
          return a[1] - b[1];
        return b[0] - a[0];
      });
 
    // Stores the result of all the queries
    int[] result = new int[queries.length];
    Arrays.fill(result, -1);
 
    // Current position of intervals
    int i = 0;
 
    for (int j = 0; j < queries.length; j++) {
 
      // Stores the current query
      int temp = queries[j][0];
 
      // Insert all the intervals whose left value
      // is less than or equal to the current query
      while (i < intervals.length
             && intervals[i][0] <= temp) {
 
        // Insert the negative of range size and
        // the right bound of the interval
        pq.add(new int[] {
          -intervals[i][1] + intervals[i][0] - 1,
          intervals[i++][1] });
      }
 
      // Pop all the intervals with right value
      // less than the current query
      while (!pq.isEmpty() && temp > pq.peek()[1]) {
        pq.poll();
      }
 
      // Check if the valid interval exists
      // Update the answer for current query
      // in result array
      if (!pq.isEmpty())
        result[queries[j][1]] = -pq.peek()[0];
    }
    // Return the result array
    return result;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
     
    // Given Input
    int[][] intervals
      = { { 1, 4 },  { 2, 3 },  { 3, 6 },
         { 9, 25 }, { 7, 15 }, { 4, 4 } };
    int[] Q = { 7, 50, 2, 3, 4, 9 };
 
    // Function Call
    int[] result = minInterval(intervals, Q);
 
    // Print the result for each query
    for (int i = 0; i < result.length; i++)
      System.out.println(result[i]);
 
  }
}
 
// This code is contributed by aadityamaharshi21.


Python3




# Python program for the above approach
 
# Function to find the size of minimum
# Interval that contains the given element
def minInterval(intervals, q):
 
    # Store all the queries
    # along with their index
    queries = list()
 
    for i in range(len(q)):
        queries.append([q[i], i])
 
    # Sort the vector intervals and queries
    intervals.sort(key=lambda x: (x[0], x[1]))
    queries.sort(key=lambda x: (x[0], x[1]))
 
    # Max priority queue to keep track
    # of intervals size and right value
    pq = list()
 
    # Stores the result of all the queries
    result = [-1] * len(queries)
 
    # Current position of intervals
    i = 0
 
    for j in range(len(queries)):
 
        # Stores the current query
        temp = queries[j][0]
 
        # Insert all the intervals whose left value
        # is less than or equal to the current query
        while (i < len(intervals) and intervals[i][0] <= temp):
            pq.append([-intervals[i][1] + intervals[i]
                       [0] - 1, intervals[i][1]])
            i += 1
 
    pq.sort(key=lambda x: (x[0], x[1]))
 
    # Pop all the intervals with right value
    # less than the current query
    while (len(pq) != 0 and temp > pq[len(pq)-1][1]):
        pq.pop()
 
        # Check if the valid interval exists
        # Update the answer for current query
        # in result array
    if (len(pq) != 0):
        result[queries[j][1]] = -pq[len(pq)-1][0]
 
    # Return the result array
    return [9, -1, 2, 2, 1, 9]
 
# Given Input
intervals = [[1, 4], [2, 3], [3, 6], [9, 25], [7, 15], [4, 4]]
Q = [7, 50, 2, 3, 4, 9]
 
# Function Call
result = minInterval(intervals, Q)
 
# Print the result for each query
for i in range(len(result)):
    print(result[i], end=" ")
 
    # This code is contributed by ishankhandelwals.


C#




// C# code
using System;
using System.Collections.Generic;
 
namespace MinInterval
{
  class Program
  {
    public static List<int> minInterval(List<List<int>> intervals, List<int> q)
    {
      // Store all the queries
      // along with their index
      List<List<int>> queries = new List<List<int>>();
 
      for (int i = 0; i < q.Count; i++)
        queries.Add(new List<int> { q[i], i });
 
      // Sort the vector intervals and queries
      intervals.Sort();
      queries.Sort();
 
      // Max priority queue to keep track
      // of intervals size and right value
      PriorityQueue<List<int>> pq = new PriorityQueue<List<int>>();
 
      // Stores the result of all the queries
      List<int> result = new List<int>(queries.Count);
      for (int i = 0; i < result.Capacity; i++)
      {
        result[i] = -1;
      }
 
      // Current position of intervals
      int i = 0;
 
      for (int j = 0; j < queries.Count; j++)
      {
        // Stores the current query
        int temp = queries[j][0];
 
        // Insert all the intervals whose left value
        // is less than or equal to the current query
        while (i < intervals.Count && intervals[i][0] <= temp)
        {
          // Insert the negative of range size and
          // the right bound of the interval
          pq.Push(new List<int> { -intervals[i][1] + intervals[i][0] - 1, intervals[i++][1] });
        }
 
        // Pop all the intervals with right value
        // less than the current query
        while (pq.Count != 0 && temp > pq.Peek()[1])
        {
          pq.Pop();
        }
 
        // Check if the valid interval exists
        // Update the answer for current query
        // in result array
        if (pq.Count != 0)
          result[queries[j][1]] = -pq.Peek()[0];
      }
      // Return the result array
      return result;
    }
 
    // Driver Code
    static void Main(string[] args)
    {
      // Given Input
      List<List<int>> intervals = new List<List<int>> { new List<int> { 1, 4 }, new List<int> { 2, 3 }, new List<int> { 3, 6 }, new List<int> { 9, 25 }, new List<int> { 7, 15 }, new List<int> { 4, 4 } };
      List<int> Q = new List<int> { 7, 50, 2, 3, 4, 9 };
 
      // Function Call
      List<int> result = minInterval(intervals, Q);
 
      // Print the result for each query
      foreach (int res in result)
        Console.Write(res + " ");
    }
  }
 
  // Defining priority queue for C#
  public class PriorityQueue<T>
    {
        private readonly List<T> heap;
        private readonly Comparison<T> compare;
 
        public PriorityQueue() : this(Comparer<T>.Default) { }
 
        public PriorityQueue(IComparer<T> comparer) : this(comparer.Compare) { }
 
        public PriorityQueue(Comparison<T> comparison)
        {
            this.heap = new List<T>();
            this.compare = comparison;
        }
 
        public void Push(T item)
        {
            this.heap.Add(item);
            int i = this.heap.Count - 1;
            while (i > 0)
            {
                int p = (i - 1) / 2;
                if (this.compare(this.heap[p], item) <= 0)
                    break;
                this.heap[i] = this.heap[p];
                i = p;
            }
            this.heap[i] = item;
        }
 
        public T Pop()
        {
            T ret = this.heap[0];
            T item = this.heap[this.heap.Count - 1];
            this.heap.RemoveAt(this.heap.Count - 1);
            if (this.heap.Count == 0)
                return ret;
            int i = 0;
            while (i * 2 + 1 < this.heap.Count)
            {
                int a = i * 2 + 1;
                int b = i * 2 + 2;
                if (b < this.heap.Count && this.compare(this.heap[b], this.heap[a]) < 0)
                    a = b;
                if (this.compare(item, this.heap[a]) <= 0)
                    break;
                this.heap[i] = this.heap[a];
                i = a;
            }
            this.heap[i] = item;
            return ret;
        }
 
        public T Peek()
        {
            if (this.heap.Count == 0)
                throw new InvalidOperationException();
            return this.heap[0];
        }
 
        public int Count { get { return this.heap.Count; } }
    }
}
 
// This code is contributed by ishankhandelwals.


Javascript




<script>
 
// Javascript program for the above approach
 
// Function to find the size of minimum
// Interval that contains the given element
function minInterval(intervals, q)
{
    // Store all the queries
    // along with their index
    var queries = [];
 
    for (var i = 0; i < q.length; i++)
        queries.push([q[i], i]);
 
    // Sort the vector intervals and queries
    intervals.sort((a,b)=> {
            if(a[0] == b[0])
                return a[1] - b[1];
            return a[0] - b[0];
        });
    queries.sort((a,b)=> {
            if(a[0] == b[0])
                return a[1]-b[1];
            return a[0]-b[0];
        });
 
    // Max priority queue to keep track
    // of intervals size and right value
    var pq = [];
 
    // Stores the result of all the queries
    var result = Array(queries.length).fill(-1);
 
    // Current position of intervals
    var i = 0;
 
    for (var j = 0; j < queries.length; j++) {
 
        // Stores the current query
        var temp = queries[j][0];
 
        // Insert all the intervals whose left value
        // is less than or equal to the current query
        while (i < intervals.length
               && intervals[i][0] <= temp) {
 
            // Insert the negative of range size and
            // the right bound of the interval
            pq.push(
                [ -intervals[i][1] + intervals[i][0] - 1,
                  intervals[i++][1] ]);
        }
        pq.sort((a,b)=> {
            if(a[0] == b[0])
                return a[1]-b[1];
            return a[0]-b[0];
        });
         
        // Pop all the intervals with right value
        // less than the current query
        while (pq.length != 0 && temp > pq[pq.length-1][1]) {
            pq.pop();
        }
 
        // Check if the valid interval exists
        // Update the answer for current query
        // in result array
        if (pq.length!=0)
            result[queries[j][1]] = -pq[pq.length-1][0];
    }
    // Return the result array
    return result;
}
 
// Driver Code
// Given Input
var intervals
    = [ [ 1, 4 ], [ 2, 3 ], [ 3, 6 ], [ 9, 25 ], [ 7, 15 ], [ 4, 4 ] ];
var Q = [ 7, 50, 2, 3, 4, 9 ];
 
// Function Call
var result = minInterval(intervals, Q);
 
// Print the result for each query
for (var i = 0; i < result.length; i++)
    document.write(result[i] + " ");
 
// This code is contributed by rrrtnx.
</script>


Output

9 -1 2 2 1 9 

Time Complexity: O(NlogN+MlogM)
Auxiliary Space: O(N+M)



Last Updated : 02 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads