力扣436(java&python)-寻找右区间(中等)
题目:
给你一个区间数组 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 <= 2 * 104
- intervals[i].length == 2
- -106 <= starti <= endi <= 106
- 每个间隔的起点都 不相同
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-right-interval
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
【二分查找】
首先理解一下题目的意思:
给了一个区间数组 intervals ,数组中的每个元素都是一个区间,且每个 区间的starti 都 不同。当区间B的起点大于等于区间A的终点,就称区间B在区间A的右侧。让我们求满足右侧区间的,起点最小的那个区间所在区间数组intervals的下标。
这里就是在某个区间找一个目标值,就会想到用二分查找法,但是二分查找法 是在有序数组中查找。加之提示中说了每个区间是start都不一样,可以试试把每个区间的start提取出来,存入到start数组中,并将start数组进行升序排序,并把每个区间的start以 <值,区间下标索引> 键值对的形式存放在一个hashmap start_map中。然后升序排序数组中使用二分查找,将每个区间的end值(target)与start数组中的mid值进行比较,最终在二分查找方法中返回满足条件的start中的下标值:
- left = 0, right = start.length, mid = left + (right - left) / 2,循环的条件是: left < right;
- 如果 start[start.length - 1] < target :说明任何区间的起点值都小于当前区间的end值,则找不到右侧区间,直接返回-1;
- 如果 start[mid] >= target :说明起点值大于等于当前区间的end值,则右边的起点值就不是第一个大于end的,则需要往左边搜索,但是mid有可能就是第一个满足条件的start值,即让right = mid;
- 如果 start[mid] < target :说明起点值小于当前区间的end值,满足条件的起点值一定在右侧,则需要往右边搜索,即让left = mid + 1;
- 循环结束的条件:left = right,left或者right都是满足条件的最小起点值。
二分查找返回了符合右侧区间中start下标索引值,根据下标索引值从start数组中获取对应的start值,然后再在start_map中获取start值对应的区间下标存入到ans数组中,最终返回ans即可。
java代码:
1 class Solution { 2 public int[] findRightInterval(int[][] intervals) { 3 int n = intervals.length; 4 Map<Integer, Integer> start_map = new HashMap<>(); 5 //存放每个区间的start 6 int[] start = new int[n]; 7 for (int i = 0; i < n; i++){ 8 start_map.put(intervals[i][0], i); 9 start[i] = intervals[i][0]; 10 } 11 Arrays.sort(start); 12 int[] ans = new int[n]; 13 for (int i = 0; i < n; i++){ 14 int temp = right_find(start, intervals[i][1]); 15 ans[i] = temp == -1 ? -1 : start_map.get(start[temp]); 16 } 17 return ans; 18 } 19 public int right_find(int[] start, int target){ 20 //如果终点大于所有的起点,则找不到右区间 21 if (target > start[start.length - 1]) return -1; 22 int left = 0, right = start.length - 1; 23 while (left < right){ 24 int mid = left + (right - left) / 2; 25 //如果起点大于等于终点 26 //则右边的数不是第一个大于终点的数,向左移 27 if (start[mid] >= target){ 28 right = mid; 29 }else{ 30 left = mid + 1; 31 } 32 } 33 return left; 34 } 35 }
python3代码:
1 class Solution: 2 def findRightInterval(self, intervals: List[List[int]]) -> List[int]: 3 n = len(intervals) 4 start = [] 5 dict = {} 6 for i in range(n): 7 dict[intervals[i][0]] = i 8 start.append(intervals[i][0]) 9 start.sort() 10 ans = [0] * n 11 for i in range(n): 12 temp = self.right_find(start, intervals[i][1]) 13 ans[i] = -1 if temp == -1 else dict[start[temp]] 14 return ans 15 16 def right_find(self, start, target): 17 n = len(start) 18 left, right = 0, n-1 19 if start[n-1] < target: 20 return -1 21 while left < right: 22 mid = left + (right - left) // 2 23 if start[mid] >= target: 24 right = mid 25 else: 26 left = mid + 1 27 return left
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理