Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

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

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

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)


My Personal Notes arrow_drop_up
Last Updated : 02 Feb, 2023
Like Article
Save Article
Similar Reads
Related Tutorials