【每日一题】1851. 包含每个查询的最小区间

【每日一题】1851. 包含每个查询的最小区间

1851. 包含每个查询的最小区间

题目描述

给你一个二维整数数组 intervals ,其中 intervals[i] = [lefti, righti] 表示第 i 个区间开始于 lefti 、结束于 righti(包含两侧取值,闭区间)。区间的 长度 定义为区间中包含的整数数目,更正式地表达是 righti - lefti + 1 。

再给你一个整数数组 queries 。第 j 个查询的答案是满足 lefti <= queries[j] <= righti 的 长度最小区间 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 <= 105
1 <= queries.length <= 105
intervals[i].length == 2
1 <= lefti <= righti <= 107
1 <= queries[j] <= 107

解题思路

思路:排序+离线查询+优先队列。通过观察,我们可以发现,查询的顺序以及区间的顺序并不会影响结果,所以我们可以先对查询以及区间排序,其中由于最后返回结果要按照初始查询顺序,故对查询排序时需要将其下标顺带存起来。对于每一个查询,遍历其所属于的长度最小的区间,那么需要满足l<=q<=r,此处相当于二维排序,我们不能一下同时处理两个维度,所以我们可以先处理l再处理r,即先将满足l<=q的收集起来,接着再从这里面去除q>r的部分,最后最小的那个区间长度即是结果。对于l部分,我们将区间按照左端点排序后就可以收集l<=q,接着我们要求最小区间,就可以使用一个小根堆,存储这些收集的l<=q,再从其中排除q>r的部分即可,此时要用到r,故可以最小堆存储区间长度和右端点即[len,r]。

class Solution {
public:
    vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries) {
        // 查询顺序不会影响答案 涉及区间也不会变化
        int n=intervals.size();
        int m=queries.size();
        // 区间按照左端点从小到大排序
        // 对区间和查询值都进行排序。排序的目的是我们可以过滤掉非备选区间:即lefti > queries[j]和righti < queries[j]
        sort(intervals.begin(),intervals.end());
        // 定义别名
        using pii=pair<int,int>;
        //查询以及原始下标
        vector<pii> qs;
        for(int i=0;i<m;i++)
            qs.emplace_back(queries[i],i);
        // 查询按照从小到大排序
        sort(qs.begin(),qs.end());
        vector<int> ans(m,-1);
        // 就和int vector<int> greater<int>一样  greater是小根堆
        // [v,r]表示区间长度 右端点
        priority_queue<pii,vector<pii>,greater<pii>> pq;
        int i=0;
        //遍历查询
        for(auto &[x,j]:qs)
        {
            //当前遍历区间   过滤掉lefti > queries[j]
            while(i<n&&intervals[i][0]<=x)
            {
                int a=intervals[i][0],b=intervals[i][1];
                //如果区间左端点小于当前查询数则加入
                pq.emplace(b-a+1,b);
                i++;
            } 
            //将右端点小于的删除    过滤掉righti < queries[j]
            while(!pq.empty()&&pq.top().second<x)
                pq.pop();
            //最后加入满足要求的
            if(!pq.empty())
                ans[j]=pq.top().first;
        }
        return ans;
    }
};

总结:对于二维数组使用sort函数,其会按照第一维度排序。priority_queue<int,vector<int>,greater<int>>是小根堆,int可以换成其他数据类型。using pii = vector<int,int>相当于使用别名。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值