开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天,点击查看活动详情
LeetCode436:寻找右区间
给你一个区间数组 intervals ,其中 intervals[i] = [starti, endi] ,且每个 starti 都 不同 。
区间 i 的 右侧区间 可以记作区间 j ,并满足 startj`` >= endi ,且 startj 最小化 。
返回一个由每个区间 i 的 右侧区间 在 intervals 中对应下标组成的数组。如果某个区间 i 不存在对应的 右侧区间 ,则下标 i 处的值设为 -1 。
示例 1:
输入: intervals = [[1,2]]
输出: [-1]
解释: 集合中只有一个区间,所以输出-1。
示例 2:
输入: intervals = [[3,4],[2,3],[1,2]]
输出: [-1,0,1]
解释: 对于 [3,4] ,没有满足条件的“右侧”区间。
对于 [2,3] ,区间[3,4]具有最小的“右”起点;
对于 [1,2] ,区间[2,3]具有最小的“右”起点。
示例 3:
输入: intervals = [[1,4],[2,3],[3,4]]
输出: [-1,2,-1]
解释: 对于区间 [1,4] 和 [3,4] ,没有满足条件的“右侧”区间。
对于 [2,3] ,区间 [3,4] 有最小的“右”起点。
提示:
intervals[i].length == 2- 每个间隔的起点都 不相同
思路分析
根据题意分析: 右侧区间定义为 满足条件(startj >= endi)的区间的最值(startj 最小化) 按 end 排序数组 index1, start 排序数组 index0 (都按升序);
从右到左遍历index1(从最大end开始), 在index0中找到满足条件的区间(从最大start开始) 放入优先级队列
- 这样遍历之前筛选满足条件的区间 后面都满足条件.
- 如果队列不为空,说明能找到 右侧区间
算法代码
class Solution {
public int[] findRightInterval(int[][] intervals) {
int n = intervals.length;
Integer[] index0 = new Integer[n];
Integer[] index1 = new Integer[n];
for (int i = 0; i != n; ++i) {
index0[i] = index1[i] = i;
}
Arrays.sort(index0, (Integer a, Integer b) - > {
return intervals[a][0] - intervals[b][0];
});
Arrays.sort(index1, (Integer a, Integer b) - > {
return intervals[a][1] - intervals[b][1];
});
int[] ans = new int[n];
for (int i = 0; i != n; ++i) {
ans[i] = -1;
}
PriorityQueue < Integer > q = new PriorityQueue < Integer > ((Integer a, Integer b) - > {
return intervals[a][0] - intervals[b][0];
});
for (int i = n - 1, j = n - 1; i >= 0; --i) {
int x = intervals[index1[i]][1];
while (j >= 0 && intervals[index0[j]][0] >= x) {
q.add(index0[j]);
--j;
}
if (!q.isEmpty()) {
ans[index1[i]] = q.peek();
}
}
return ans;
}
}
结果详情
算法复杂度
- 空间复杂度:
- 时间复杂度:
在掘金(JUEJIN)一起进步,一起成长!