包含每个查询的最小区间

给你一个二维整数数组 intervals ,其中 intervals[i] = [lefti, righti] 表示第 i 个区间开始于 lefti 、结束于 righti(包含两侧取值,闭区间)。
区间的长度定义为区间中包含的整数数目,更正式地表达是 righti - lefti + 1 。
再给你一个整数数组 queries 。第 j 个查询的答案是满足 lefti <= queries[j] <= righti 的 长度最小区间 i 的长度 。
如果不存在这样的区间,那么答案是 -1 。以数组形式返回对应查询的所有答案

1. 离线查询 + 优先队列

由于要找最小区间长度,必然要采取某种贪心策略
对于查询点,找左边界小于查询点,同时右边界大于查询点的区间
这里使用优先队列方便查找最小的区间
同时对不满足条件的区间移出队列

class Solution {
public:
    vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries) {
        vector<int> qindex(queries.size()); //从小到大记录查询点下标
        iota(qindex.begin(), qindex.end(), 0);
        sort(qindex.begin(), qindex.end(), [&](int i, int j){
            return queries[i] < queries[j];
        });
        sort(intervals.begin(), intervals.end(), [](const vector<int> &it1, const vector<int> &it2){//区间按左边界进行排序
            return it1[0] < it2[0];
        });
        priority_queue<vector<int>> pq;//优先队列
        vector<int> res(queries.size(), -1);//不满足条件为-1
        int i = 0; //区间点下标
        for (auto qi : qindex) { //从左到右遍历查询点
            while (i < intervals.size() && intervals[i][0] <= queries[qi]) {//处理左边界小于查询点的区间
                int l = intervals[i][1] - intervals[i][0] + 1;//计算当前区间长度
                pq.push({-l, intervals[i][0], intervals[i][1]});//将候选区间入队、按长度升序排
                i++;
            }
            while (!pq.empty() && pq.top()[2] < queries[qi]) {//右边界小于查询点,之后没用,移出队列
                pq.pop();
            }
            if (!pq.empty()) {//第一个必然是满足条件的最小区间
                res[qi] = -pq.top()[0];
            }
        }
        return res;
    }
};
posted @ 2023-07-19 06:15  失控D大白兔  阅读(12)  评论(0编辑  收藏  举报