LeetCode 436. 寻找右区间 (排序 / 二分 / 哈希表)

在这里插入图片描述

思路

TreeMap
根据题目描述,注意几个地方,每个start[i]都不同,而且要求start[j]>=end[i],很容易联想到使用带排序的哈希结构,也就是TreeMap,具体实现为:

  1. 第一次遍历 intervals,完成TreeMap的构造,key为左端点,value为index位置;
  2. 第二次遍历 intervals,对每个interval的右端点取ceiling,如果不存在,即为-1,填充在结果集中;

排序 + 二分
为了方便,我们称 intervals 为 its。
对于每个 its[i] 而言,我们需要在所有满足 its[j][0] ⩾ its[i][1] 中找到 its[j][0] 值最小的下标 jj,并将其记为 ans[i]。
对于一个特定的 its[i] 而言,其右端点固定,并且我们只关心目标位置的左端点。
因此我们可以构造一个记录区间左端点的数组 clone,并将其进行排序,同时为了记录每个左端点来自于原序列中的那个下标,还需要额外记录原序列下标,即以 (start,idx) 二元组的形式进行转存,并根据 start 排序。
然后从前往后处理每个 its[i],运用「二分」在 clone 中找到第一个满足左端点 start 大于等于 its[i][1] 的成员 clone[j],将其 clone[j][1] 即是 its[i] 的最右区间。

代码实现(java)

class Solution {
    public int[] findRightInterval(int[][] intervals) {
        // 排序 + 二分
        int n = intervals.length;
        int[][] clone = new int[n][2];
        for(int i = 0; i < n; i++) {
            // 将数组的第一个元素及其下标记录起来
            clone[i] = new int[]{intervals[i][0], i};
        }

        Arrays.sort(clone, (o1, o2) -> o1[0] - o2[0]);
        int[] res = new int[n];
        for(int i = 0; i < n; i++) {
            int l = 0, r = n - 1;
            while(l < r) {
                int mid = l + (r - l) / 2;
                // 找到最左边的边界
                if (clone[mid][0] >= intervals[i][1]) r = mid;
                else l = mid + 1;
            }
            // 如果r所在位置的左边界确实大于当前位置的右边界,则取出下标存入res,否则存入-1
            res[i] = clone[r][0] >= intervals[i][1] ? clone[r][1] : -1;
        }

        return res;


		// TreeMap方法
        // TreeMap<Integer, Integer> map = new TreeMap<>();
        // int n = intervals.length;
        // for (int i = 0; i < intervals.length; i++) {
        //     map.put(intervals[i][0], i);
        // }

        // int[] res = new int[n];
        // for(int i = 0; i < n; i++) {
        //     Integer j = map.ceilingKey(intervals[i][1]);
        //     if(j == null) res[i] = -1;
        //     else res[i] = map.get(j);
        // }
        
        // return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值