[LeetCode] 436. Find Right Interval

You are given an array of intervals, where intervals[i] = [starti, endi] and each starti is unique.

The right interval for an interval i is an interval j such that startj >= endi and startj is minimized. Note that i may equal j.

Return an array of right interval indices for each interval i. If no right interval exists for interval i, then put -1 at index i.

Example 1:

Input: intervals = [[1,2]]
Output: [-1]
Explanation: There is only one interval in the collection, so it outputs -1.

Example 2:

Input: intervals = [[3,4],[2,3],[1,2]]
Output: [-1,0,1]
Explanation: There is no right interval for [3,4].
The right interval for [2,3] is [3,4] since start0 = 3 is the smallest start that is >= end1 = 3.
The right interval for [1,2] is [2,3] since start1 = 2 is the smallest start that is >= end2 = 2.

Example 3:

Input: intervals = [[1,4],[2,3],[3,4]]
Output: [-1,2,-1]
Explanation: There is no right interval for [1,4] and [3,4].
The right interval for [2,3] is [3,4] since start2 = 3 is the smallest start that is >= end1 = 3.

Constraints:

  • 1 <= intervals.length <= 2 * 104
  • intervals[i].length == 2
  • -106 <= starti <= endi <= 106
  • The start point of each interval is unique.

寻找右区间。

给你一个区间数组 intervals ,其中 intervals[i] = [starti, endi] ,且每个 starti 都 不同 。

区间 i 的 右侧区间 可以记作区间 j ,并满足 startj >= endi ,且 startj 最小化 。

返回一个由每个区间 i 的 右侧区间 的最小起始位置组成的数组。如果某个区间 i 不存在对应的 右侧区间 ,则下标 i 处的值设为 -1 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-right-interval
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题意是给一个 list,里面装的是一些 interval 区间,对于每个 interval i,请你寻找是否存在另外一个 interval j,满足 j 在 i 的右边。在右边的定义是 j 的起点要大于等于 i 的终点。对于每一个 interval i,如果能找到一个这样的 j 区间,则返回 j 的下标,否则返回-1。

这道题有两种做法,一种是treemap,一种是二分法。

首先介绍 treemap 的做法。遍历 input,将每个区间的起点当做 key,每个区间的下标当做 value 放入 treemap。再次遍历 input,此时会利用到 treemap 的一个函数叫做ceilingKey(),找当前 map 中是否存在一个最小的区间的起点,这个起点比当前遍历到的区间的终点要大。如果找到,则放入结果集。

时间O(nlogn) - treemap search

空间O(n)

Java实现

 1 class Solution {
 2     public int[] findRightInterval(int[][] intervals) {
 3         int[] res = new int[intervals.length];
 4         TreeMap<Integer, Integer> map = new TreeMap<>();
 5         for (int i = 0; i < intervals.length; i++) {
 6             map.put(intervals[i][0], i);
 7         }
 8 
 9         for (int i = 0; i < intervals.length; i++) {
10             Integer key = map.ceilingKey(intervals[i][1]);
11             res[i] = key != null ? map.get(key) : -1;
12         }
13         return res;
14     }
15 }

 

二分法稍微复杂一点。所有做二分的题目,二分的前提是被二分查找的数组应该是有序的,但是这道题我们不能对 input 数组进行排序。这里我们需要额外使用一个数组 arr,记录每个区间的起点,我们还需要一个hashmap,记录每个区间的<起点,下标>对应关系。我参考了这个帖子

我们先遍历一遍 input 数组,把数据预处理一下,arr 记录了每个区间的起点,hashmap 记录了每个子区间的起点和下标。接着我们开始遍历每个子区间,对于每个子区间的终点 end,我们要去 arr 数组里找一个大于 end 的最小的起点。因为 arr 数组此时已经是有序的了,所以这里可以用二分。如果找不到这个起点就返回 -1,如果能找到这个起点的话,那么我们再去 hashmap 里找出这个起点对应的下标 i 即可,存入结果集。

时间:排序O(nlogn), 预处理O(n), 二分O(logn) = O(nlogn)

空间O(n) - hashmap 和 arr 数组

Java实现

 1 class Solution {
 2     public int[] findRightInterval(int[][] intervals) {
 3         int len = intervals.length;
 4         HashMap<Integer, Integer> map = new HashMap<>();
 5         // arr存的是每个interval的start
 6         int[] arr = new int[len];
 7         int[] res = new int[len];
 8         for (int i = 0; i < len; i++) {
 9             map.put(intervals[i][0], i);
10             arr[i] = intervals[i][0];
11         }
12         
13         Arrays.sort(arr);
14         for (int i = 0; i < len; i++) {
15             int index = binarySearch(arr, intervals[i][1]);
16             if (index == -1) {
17                 res[i] = -1;
18             } else {
19                 res[i] = map.get(arr[index]);
20             }
21         }
22         return res;
23     }
24     
25     private int binarySearch(int[] arr, int target) {
26         int len = arr.length;
27         // corner case
28         if (arr[len - 1] < target) {
29             return -1;
30         }
31         
32         int left = 0;
33         int right = len - 1;
34         while (left < right) {
35             int mid = left + (right - left) / 2;
36             if (arr[mid] < target) {
37                 left = mid + 1;
38             } else {
39                 right = mid;
40             }
41         }
42         return left;
43     }
44 }

 

LeetCode 题目总结

posted @ 2020-08-28 06:48  CNoodle  阅读(245)  评论(0编辑  收藏  举报