Minimum Interval to Include Each Query 包含每个查询的最小区间
问题描述:
给你一个二维整数数组 intervals ,其中 intervals[i] = [ l e f t i , r i g h t i ] [left_i, right_i] [lefti,righti] 表示第 i 个区间开始于 l e f t i left_i lefti 、结束于 r i g h t i right_i righti(包含两侧取值,闭区间)。区间的 长度 定义为区间中包含的整数数目,更正式地表达是 r i g h t i − l e f t i + 1 right_i - left_i + 1 righti−lefti+1 。
再给你一个整数数组 queries 。第 j 个查询的答案是满足 l e f t i < = q u e r i e s [ j ] < = r i g h t i left_i <= queries[j] <= right_i lefti<=queries[j]<=righti 的 长度最小区间 i 的长度 。如果不存在这样的区间,那么答案是 -1 。
以数组形式返回对应查询的所有答案
1 < = i n t e r v a l s . l e n g t h < = 1 0 5 1 < = q u e r i e s . l e n g t h < = 1 0 5 i n t e r v a l s [ i ] . l e n g t h = = 2 1 < = l e f t i < = r i g h t i < = 1 0 7 1 < = q u e r i e s [ j ] < = 1 0 7 1 <= intervals.length <= 10^5\\ 1 <= queries.length <=10^5\\ intervals[i].length == 2\\ 1 <= left_i <= right_i <= 10^7\\ 1 <= queries[j] <= 10^7 1<=intervals.length<=1051<=queries.length<=105intervals[i].length==21<=lefti<=righti<=1071<=queries[j]<=107
分析
区间的规模最大 1 0 5 10^5 105,通常的思路,进行一次查询,必然就是遍历,与每个区间都进行比较,记录下符合条件的区间的下标,并且在过程中找到最小。
单次的时间复杂度就是 O ( N ) O(N) O(N),而queries的规模最大也是 1 0 5 10^5 105,所以很明显TLE.
如果对 i n t e r v a l interval interval进行排序,以left从低到高进行排序,时间复杂度 O ( N l o g N ) O(NlogN) O(NlogN),每次查找到最后1个符合条件的位置 i d x idx idx,即 0 → i d x 0\rightarrow idx 0→idx,都是符合 l e f t < = q u e r i e s [ i ] left<=queries[i] left<=queries[i],只需要在这个范围内进行遍历即可,单次的时间复杂度 O ( l o g N + M ) O( logN + M) O(logN+M).
但是在最差的情况下,依然会达到 O ( M N ) O(MN) O(MN).
其实这个思路缺少了一个环节,如果每次查询后,可以缩小后续查询的范围,就可以有加速的效果。
将queries也排序从小到大,interval以left递增,并且以区间的大小从小到大排序。
对于
q
u
e
r
i
e
s
[
i
]
queries[i]
queries[i],将
0
→
i
d
x
0 \rightarrow idx
0→idx,都满足
l
e
f
t
<
=
q
u
e
r
i
e
s
[
i
]
left<=queries[i]
left<=queries[i],入优先队列。此时队列中都是left符合条件,并且区间最小的区间,但是不能保证
r
i
g
h
t
>
=
q
u
e
r
i
e
s
[
i
]
right>=queries[i]
right>=queries[i],所以需要将队首元素进行验证,如果
r
i
g
h
t
<
q
u
e
r
i
e
s
[
i
]
right<queries[i]
right<queries[i],可以直接出队,因为
r
i
g
h
t
<
q
u
e
r
i
e
s
[
i
]
right<queries[i]
right<queries[i],一定也
r
i
g
h
t
<
q
u
e
r
i
e
s
[
j
]
right<queries[j]
right<queries[j].
因为queries是按照顺序出结果,所以需要记录queries的原来的顺序,然后进行索引排序。
代码
class Solution {
public int[] minInterval(int[][] intervals, int[] queries) {
Integer[] qindex = new Integer[queries.length];
for (int i = 0; i < queries.length; i++) {
qindex[i] = i;
}
Arrays.sort(qindex, (i, j) -> queries[i] - queries[j]);
Arrays.sort(intervals, (i, j) -> i[0] - j[0]);
// scope,left,right
PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a, b) -> a[0] - b[0]);
int[] res = new int[queries.length];
Arrays.fill(res, -1);
int i = 0;
for (int qi : qindex) {
while (i < intervals.length && intervals[i][0] <= queries[qi]) {
pq.offer(new int[]{intervals[i][1] - intervals[i][0] + 1, intervals[i][0], intervals[i][1]});
i++;
}
while (!pq.isEmpty() && pq.peek()[2] < queries[qi]) {
pq.poll();
}
if (!pq.isEmpty()) {
res[qi] = pq.peek()[0];
}
}
return res;
}
}
时间复杂度 O ( M log M + N log N ) O(M\log M+ N\log N) O(MlogM+NlogN)
空间复杂度 O ( M + N ) O(M+N) O(M+N)
Tag
Array
Sorting
Priority Queue