Leetcode P5748 包含每个查询的最小区间
给你一个二维整数数组 intervals ,其中 intervals[i] = [left_i, right_i] 表示第 i 个区间开始于 left_i 、结束于 right_i(包含两侧取值,闭区间)。区间的 长度 定义为区间中包含的整数数目,更正式地表达是 right_i - left_i + 1 。
再给你一个整数数组 queries 。第 j 个查询的答案是满足 left_i <= queries[j] <= right_i 的 长度最小区间 i 的长度 。如果不存在这样的区间,那么答案是 -1 。
以数组形式返回对应查询的所有答案。
示例1:
输入:intervals = [[1,4],[2,4],[3,6],[4,4]], queries = [2,3,4,5]
输出:[3,3,1,4]
解释:查询处理如下:
- Query = 2 :区间 [2,4] 是包含 2 的最小区间,答案为 4 - 2 + 1 = 3 。
- Query = 3 :区间 [2,4] 是包含 3 的最小区间,答案为 4 - 2 + 1 = 3 。
- Query = 4 :区间 [4,4] 是包含 4 的最小区间,答案为 4 - 4 + 1 = 1 。
- Query = 5 :区间 [3,6] 是包含 5 的最小区间,答案为 6 - 3 + 1 = 4 。
示例2:
输入:intervals = [[2,3],[2,5],[1,8],[20,25]], queries = [2,19,5,22]
输出:[2,-1,4,6]
解释:查询处理如下:
- Query = 2 :区间 [2,3] 是包含 2 的最小区间,答案为 3 - 2 + 1 = 2 。
- Query = 19:不存在包含 19 的区间,答案为 -1 。
- Query = 5 :区间 [2,5] 是包含 5 的最小区间,答案为 5 - 2 + 1 = 4 。
- Query = 22:区间 [20,25] 是包含 22 的最小区间,答案为 25 - 20 + 1 = 6 。
提示:
- 1 <= intervals.length <= 10^5
- 1 <= queries.length <= 10^5
- queries[i].length == 2
- 1 <= left_i <= right_i <= 10^7
- 1 <= queries[j] <= 10^7
leetcode最近经常出这种离线思维的题作为最后一题,普遍的一个思路是离线对queries数组进行某种排序,然后更新会在接下来queries中出现的所有区间,在logn时间以内获得单位查询的解。
但是这道题我却没能做出来。能够想到对queries大小进行排序,然后我想的是对于一个新的query num,对所有的区间排序,除去所有right值小于num和left值大于num的,用集合维护剩下的区间,每次取出长度最小的。但在除去…这一步犯了难,right值小于num的好删,随着num增大不断删除新的区间即可,但集合中left值大于num的元素怎么删?
其实刚刚这个思路就差一点了,刚刚总是想竭力维护一个集合,这个集合内是所有满足 l ≤ n u m ≤ r l \leq num\leq r l≤num≤r的区间。但其实我们并不一定要刚好维护集合内所有的元素都满足这个条件:可以把区间排个序,每次把l值小于等于num的区间加入集合。然后怎么删除不满足的区间?不需要直接删除,因为我们每次也只是需要一个集合端点而已,我们判断集合端点是否满足条件,满足就是他,不满足再删。
- 离线处理queries
- 这里是用一个{区间长度,区间右端点}表示一个区间
class Solution {
public:
vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries) {
int m = queries.size(), n = intervals.size();
vector<int> q;
for (int i = 0; i < m; i++) q.push_back(i);
sort(q.begin(), q.end(), [&](int a, int b) {
return queries[a] < queries[b];
});
vector<int> res(m);
sort(intervals.begin(), intervals.end());
set<pair<int, int>> s;
int id = -1;
for (int i = 0; i < m; i++) {
while (id + 1 < n && intervals[id + 1][0] <= queries[q[i]]) {
id++;
s.insert({ intervals[id][1] - intervals[id][0] + 1, intervals[id][1] });
}
while (!s.empty() && s.begin()->second < queries[q[i]]) s.erase(s.begin());
if (s.empty()) res[q[i]] = -1;
else res[q[i]] = s.begin()->first;
}
return res;
}
};