算法初探LeetCode-寻找右区间

77 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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] 有最小的“右”起点。

提示:

  • 1<= intervals.length<=21041 <= intervals.length <= 2 * 10^4
  • intervals[i].length == 2
  • 106<=starti<=endi<=106-10^6 <= starti <= endi <= 10^6
  • 每个间隔的起点都 不相同

思路分析

根据题意分析: 右侧区间定义为 满足条件(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;
    }
}

结果详情

Snipaste_2023-02-28_23-08-48.png

算法复杂度

  • 空间复杂度:O(n)O(n)
  • 时间复杂度:O(nlogn)O(nlogn)

掘金(JUEJIN)一起进步,一起成长!