1. 问题描述:
给你一个区间数组 intervals ,其中 intervals[i] = [starti, endi] ,且每个 starti 都不同 。区间 i 的右侧区间可以记作区间 j ,并满足 startj >= endi ,且 startj 最小化 。返回一个由每个区间 i 的右侧区间的最小起始位置组成的数组。如果某个区间 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 <= 2 * 10 ^ 4
intervals[i].length == 2
-10 ^ 6 <= starti <= endi <= 10 ^ 6
每个间隔的起点都不相同
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-right-interval
2. 思路分析:
题目的意思是对于intervals中每一个区间找到右侧区间的最靠左区间,也即找到左端点大于等于当前区间右端点最靠左的某一个区间,找不到的时候那么当前位置的结果就为-1,如何快速找到这个区间呢?我们其实是可以使用二分来解决的,先对区间左端点由小到大排序,因为最终需要返回的是所求区间的下标,所以这里使用到的一个小技巧是一开始的时候先将下标追加到每一个位置列表元素的后面,这样排序之后区间下标是与区间是绑定的,也就可以使用二分了,枚举中点位置的区间判断中间位置区间的左端点是否大于等于当前所求区间的右端点,如果满足说明答案应该是在mid左边,所以更新r = mid,否则更新l = mid + 1,循环结束之后判断当前r位置对应的区间的右端点是否大于等于当前所求区间的左端点即可。
3. 代码如下:
from typing import List
class Solution:
# 排序之后二分即可
def findRightInterval(self, s: List[List[int]]) -> List[int]:
# 这里使用到的一个技巧是直接将下标存储到当前位置的最后面这样排序的时候区间是与下标绑定在一起的
n = len(s)
res = [-1] * n
for i in range(n):
s[i].append(i)
s.sort()
for x in s:
l, r = 0, n - 1
while l < r:
mid = l + r >> 1
if s[mid][0] >= x[1]:
r = mid
else:
l = mid + 1
# 判断当前找到的区间是否满足条件
if s[r][0] >= x[1]:
res[x[2]] = s[r][2]
return res