Leetcode P5748 包含每个查询的最小区间

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 lnumr的区间。但其实我们并不一定要刚好维护集合内所有的元素都满足这个条件:可以把区间排个序,每次把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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值