Minimum Interval to Include Each Query

hard intervals heap offline

Problem

You are given a set of intervals, each written as [left, right] and covering every integer from left to right; the size of an interval is right − left + 1. You are also given a list of integer queries.

For every query q, report the size of the smallest interval that contains q (left ≤ q ≤ right), or −1 if no interval contains it. Answers must come back in the original query order.

Inputintervals = [[1,4],[2,4],[3,6],[4,4]], queries = [2,3,4,5]
Output[3,3,1,4]
Query 2 fits in [1,4] (size 4) and [2,4] (size 3), so the smallest is 3; query 4 fits in the tiny [4,4] (size 1); query 5 only fits in [3,6] (size 4).

import heapq

def min_interval(intervals, queries):
    intervals.sort()
    order = sorted(range(len(queries)), key=lambda j: queries[j])
    ans = [-1] * len(queries)
    heap = []  # (size, right)
    i = 0
    for j in order:
        q = queries[j]
        while i < len(intervals) and intervals[i][0] <= q:
            l, r = intervals[i]
            heapq.heappush(heap, (r - l + 1, r))
            i += 1
        while heap and heap[0][1] < q:
            heapq.heappop(heap)
        if heap:
            ans[j] = heap[0][0]
    return ans
function minInterval(intervals, queries) {
  intervals.sort((a, b) => a[0] - b[0]);
  const order = queries.map((q, j) => j).sort((a, b) => queries[a] - queries[b]);
  const ans = new Array(queries.length).fill(-1);
  const heap = []; // [size, right], min-heap keyed by size
  const less = (a, b) => heap[a][0] < heap[b][0];
  const swap = (a, b) => { [heap[a], heap[b]] = [heap[b], heap[a]]; };
  const push = (v) => {
    heap.push(v);
    for (let k = heap.length - 1; k > 0 && less(k, (k - 1) >> 1); k = (k - 1) >> 1) swap(k, (k - 1) >> 1);
  };
  const pop = () => {
    swap(0, heap.length - 1); heap.pop();
    for (let k = 0, m = 0; ; k = m) {
      if (2 * k + 1 < heap.length && less(2 * k + 1, m)) m = 2 * k + 1;
      if (2 * k + 2 < heap.length && less(2 * k + 2, m)) m = 2 * k + 2;
      if (m === k) return;
      swap(k, m);
    }
  };
  let i = 0;
  for (const j of order) {
    const q = queries[j];
    while (i < intervals.length && intervals[i][0] <= q)
      push([intervals[i][1] - intervals[i][0] + 1, intervals[i++][1]]);
    while (heap.length && heap[0][1] < q) pop();
    if (heap.length) ans[j] = heap[0][0];
  }
  return ans;
}
int[] minInterval(int[][] intervals, int[] queries) {
    Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
    Integer[] order = new Integer[queries.length];
    for (int j = 0; j < order.length; j++) order[j] = j;
    Arrays.sort(order, (a, b) -> queries[a] - queries[b]);
    int[] ans = new int[queries.length];
    Arrays.fill(ans, -1);
    PriorityQueue<int[]> heap = new PriorityQueue<>((a, b) -> a[0] - b[0]);
    int i = 0;
    for (int j : order) {
        int q = queries[j];
        while (i < intervals.length && intervals[i][0] <= q) {
            int[] iv = intervals[i++];
            heap.offer(new int[]{iv[1] - iv[0] + 1, iv[1]});
        }
        while (!heap.isEmpty() && heap.peek()[1] < q) heap.poll();
        if (!heap.isEmpty()) ans[j] = heap.peek()[0];
    }
    return ans;
}
vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries) {
    sort(intervals.begin(), intervals.end());
    vector<int> order(queries.size());
    iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(),
         [&](int a, int b) { return queries[a] < queries[b]; });
    vector<int> ans(queries.size(), -1);
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> heap;
    size_t i = 0;
    for (int j : order) {
        int q = queries[j];
        while (i < intervals.size() && intervals[i][0] <= q) {
            heap.push({intervals[i][1] - intervals[i][0] + 1, intervals[i][1]});
            i++;
        }
        while (!heap.empty() && heap.top().second < q) heap.pop();
        if (!heap.empty()) ans[j] = heap.top().first;
    }
    return ans;
}
Time: O((n + q) log (n + q)) Space: O(n + q)