Skip to content
本页目录

0436-寻找右区间

题目描述

https://leetcode.cn/problems/find-right-interval

给你一个区间数组 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 * 10^4
  • intervals[i].length == 2
  • -10^6 <= starti <= endi <= 10^6
  • 每个间隔的起点都 不相同

思路:暴力法

因为我们要取得数组的索引,所以不能直接原地排序数组。

暴力搜索,对于每个数 intervals[i][1] 遍历 j 找出右区间, 即 intervals[j][0] >= 它。 这里需要注意的是,他需要找最小的那个右区间,而不是 索引 最小的那个,所以我们还需要记录一个差值,如果当前差值小于之前的差值我们才替换。

csharp
public class Solution {
    public int[] FindRightInterval(int[][] intervals) {
        //暴力搜索
        int n = intervals.Length;
        int[] result = new int[n];
        for(int i=0; i<intervals.Length; i++){
            int index = -1;
            int sub = int.MaxValue; //差值
            for(int j=0; j<intervals.Length; j++){
                if(intervals[j][0] >= intervals[i][1]){
                    if(intervals[j][0] - intervals[i][1] < sub){
                        index = j;
                        sub = intervals[j][0] - intervals[i][1]; 
                    }
                }
            }
            result[i] = index;
        }
        return result;
    }
}

思路:二分查找

上述暴力法可以通过,但是时间复杂度是 O(n^2) 我们可以将区间起点记录到一个数组,然后将索引记录到新数组。

再 使用二分法查找对应的结果,满足条件时记录 索引值。

csharp
public class Solution {
    public int[] FindRightInterval(int[][] intervals) {
        //二分查找
        int n = intervals.Length;
        int[] result = new int[n];
        int[][] ints = new int[n][];
        for(int i=0; i<n; i++){ 
            ints[i] = new int[]{intervals[i][0],i}; //记录左边界,记录索引
        }
        //排序左边界
        Array.Sort(ints,(a,b)=>{
            return a[0].CompareTo(b[0]);
        });
        //输出排序数组
        // for(int i=0; i<n; i++){
        //     Console.WriteLine("ints[{0}={1},{2}]",i,ints[i][0],ints[i][1]);
        // }

        //二分查找
        for(int i=0; i<n; i++){
            int left = 0;
            int right = n-1;
            int target = -1;
            while(left <= right){
                int mid = left + (right - left) / 2;
                if(intervals[i][1] <= ints[mid][0]){
                    target = ints[mid][1];
                    right = mid - 1;
                }
                else{
                    left = mid + 1;
                }                
            }
            result[i] = target;
        }
        return result;
    }
}

思路:双指针

将开始位置的数值和索引也加入数组,进行排序,这样就不用二分查找结束的位置。

csharp
public class Solution{

	public int[] FindRightInterval(int[][] intervals){

		int n = intervals.Length;
		int[] result = new int[n];

		int[][] startIntervals = new int[n][]; //开始位置集合
		int[][] endIntervals = new int[n][]; //结束位置集合

		for(int i=0; i<n; i++){
			startIntervals[i] = new int[]{intervals[i][0],i};
			endIntervals[i] = new int[]{intervals[i][1],i};
		}

		Array.Sort(startIntervals,(a,b)=>{return a[0].CompareTo(b[0]);});
		Array.Sort(endIntervals,(a,b)=>{return a[0].CompareTo(b[0]);});

		int j=0;
		for(int i=0; i<n; i++){
			while(j < n && startIntervals[j][0] < endIntervals[i][0]){
				j++;
			}
			if(j < n){
				result[endIntervals[i][1]] = startIntervals[j][1];
			}
			else{
				result[endIntervals[i][1]] = -1;
			}
		}
		return result;
	}
}

复习: 20220712

csharp
public class Solution{

    public int[] FindRightInterval(int[][] intervals){

        int n = intervals.Length;
        int[] result = new int[n];

        int[][] startIntervals = new int[n][]; //开始位置集合
        int[][] endIntervals = new int[n][]; //结束位置集合

        //将开始节点和结束节点的索引都加入进去
        for(int i=0; i<n; i++){
            startIntervals[i] = new int[]{intervals[i][0],i};
            endIntervals[i] = new int[]{intervals[i][1],i};
        }

        //按照开始节点排序
        Array.Sort(startIntervals,(a,b)=>{return a[0].CompareTo(b[0]);});
        //按照结束节点排序
        Array.Sort(endIntervals,(a,b)=>{return a[0].CompareTo(b[0]);});

        int j=0;
        //遍历结束节点
        for(int i=0; i<n; i++){
            //因为是要考虑右区间,因为开始节点在我之前的都不做考虑
            while(j < n && startIntervals[j][0] < endIntervals[i][0]){
                j++;
            }
            //如果j还存在,j就是目前最小的那个右区间,取出他的索引,更新到 result 里面去
            if(j < n){
                result[endIntervals[i][1]] = startIntervals[j][1];
            }
            else{ //如果 j 不存在,则赋值为 -1
                result[endIntervals[i][1]] = -1;
            }
        }
        return result;
    }
}

Released under the MIT License.