import heapq
def minInterval(intervals, queries):
intervals.sort()
queries_sorted = sorted((q, i) for i, q in enumerate(queries))
res = [0] * len(queries)
min_heap = []
i = 0
n = len(intervals)
for q, idx in queries_sorted:
# Add all intervals starting before or at q
while i < n and intervals[i][0] <= q:
start, end = intervals[i]
heapq.heappush(min_heap, (end - start + 1, end))
i += 1
# Remove intervals that end before q
while min_heap and min_heap[0][1] < q:
heapq.heappop(min_heap)
# The top of the heap is the smallest interval covering q
res[idx] = min_heap[0][0] if min_heap else -1
return res
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries) {
sort(intervals.begin(), intervals.end());
vector<pair<int, int>> queries_sorted;
int qn = queries.size();
for (int i = 0; i < qn; ++i)
queries_sorted.push_back({queries[i], i});
sort(queries_sorted.begin(), queries_sorted.end());
vector<int> res(qn);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> minHeap;
int i = 0, n = intervals.size();
for (auto& [q, idx] : queries_sorted) {
while (i < n && intervals[i][0] <= q) {
minHeap.push({intervals[i][1] - intervals[i][0] + 1, intervals[i][1]});
++i;
}
while (!minHeap.empty() && minHeap.top().second < q)
minHeap.pop();
res[idx] = minHeap.empty() ? -1 : minHeap.top().first;
}
return res;
}
import java.util.*;
public class Solution {
public int[] minInterval(int[][] intervals, int[] queries) {
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
int n = queries.length;
int[] res = new int[n];
int[][] queryWithIdx = new int[n][2];
for (int i = 0; i < n; i++) {
queryWithIdx[i][0] = queries[i];
queryWithIdx[i][1] = i;
}
Arrays.sort(queryWithIdx, (a, b) -> Integer.compare(a[0], b[0]));
PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> Integer.compare(a[0], b[0]));
int i = 0, m = intervals.length;
for (int[] q : queryWithIdx) {
int query = q[0], idx = q[1];
while (i < m && intervals[i][0] <= query) {
minHeap.offer(new int[]{intervals[i][1] - intervals[i][0] + 1, intervals[i][1]});
i++;
}
while (!minHeap.isEmpty() && minHeap.peek()[1] < query)
minHeap.poll();
res[idx] = minHeap.isEmpty() ? -1 : minHeap.peek()[0];
}
return res;
}
}
function minInterval(intervals, queries) {
intervals.sort((a, b) => a[0] - b[0]);
let queriesSorted = queries.map((q, i) => [q, i]).sort((a, b) => a[0] - b[0]);
let res = Array(queries.length);
let minHeap = [];
let i = 0, n = intervals.length;
const pushHeap = (heap, item) => {
heap.push(item);
let idx = heap.length - 1;
while (idx > 0) {
let parent = Math.floor((idx - 1) / 2);
if (heap[parent][0] <= heap[idx][0]) break;
[heap[parent], heap[idx]] = [heap[idx], heap[parent]];
idx = parent;
}
};
const popHeap = (heap) => {
if (heap.length === 1) return heap.pop();
let top = heap[0];
heap[0] = heap.pop();
let idx = 0, len = heap.length;
while (true) {
let left = 2 * idx + 1, right = 2 * idx + 2, minIdx = idx;
if (left < len && heap[left][0] < heap[minIdx][0]) minIdx = left;
if (right < len && heap[right][0] < heap[minIdx][0]) minIdx = right;
if (minIdx === idx) break;
[heap[minIdx], heap[idx]] = [heap[idx], heap[minIdx]];
idx = minIdx;
}
return top;
};
for (let [q, idx] of queriesSorted) {
while (i < n && intervals[i][0] <= q) {
pushHeap(minHeap, [intervals[i][1] - intervals[i][0] + 1, intervals[i][1]]);
i++;
}
while (minHeap.length && minHeap[0][1] < q) popHeap(minHeap);
res[idx] = minHeap.length ? minHeap[0][0] : -1;
}
return res;
}
You are given a list of intervals
, where each interval is represented by a pair [start, end]
, and a list of queries
. For each query value q
in queries
, you need to find the length of the smallest interval from intervals
that includes q
(i.e., start <= q <= end
). If no interval contains q
, return -1
for that query.
Key constraints:
queries
.The most straightforward way to solve the problem is to, for each query, check every interval to see if it contains the query, and keep track of the one with the smallest length. However, this brute-force approach is very slow if the number of intervals and queries are large, because it would require checking all intervals for each query.
To optimize, we notice that:
Let's break down the optimized algorithm step-by-step:
This approach ensures we only process each interval and query once, and we efficiently keep track of the best interval for each query.
Suppose intervals = [[1,4],[2,4],[3,6],[4,4]]
and queries = [2,3,4,5]
.
[[1,4],[2,4],[3,6],[4,4]]
[(2,0),(3,1),(4,2),(5,3)]
Final result: [3,3,1,4]
Brute-force approach:
The optimized approach is much faster and feasible for large inputs.
The key to efficiently solving the "Minimum Interval to Include Each Query" problem is to process both intervals and queries in sorted order, and use a min-heap to quickly find the smallest interval covering each query. This avoids the inefficiency of brute-force checking and leverages efficient data structures for fast lookups and removals. The algorithm is elegant because it only processes each element once and maintains only the necessary candidates in the heap at each step.