[LeetCoee] 436. Find Right Interval 解题报告

Given a set of intervals, for each of the interval i, check if there exists an interval j whose start point is bigger than or equal to the end point of the interval i, which can be called that j is on the "right" of i.

For any interval i, you need to store the minimum interval j's index, which means that the interval j has the minimum start point to build the "right" relationship for interval i. If the interval j doesn't exist, store -1 for the interval i. Finally, you need output the stored value of each interval as an array.

Note:

  1. You may assume the interval's end point is always bigger than its start point.
  2. You may assume none of these intervals have the same start point.

Example 1:

Input: [ [1,2] ]

Output: [-1]

Explanation: There is only one interval in the collection, so it outputs -1.

Example 2:

Input: [ [3,4], [2,3], [1,2] ]

Output: [-1, 0, 1]

Explanation: There is no satisfied "right" interval for [3,4].
For [2,3], the interval [3,4] has minimum-"right" start point;
For [1,2], the interval [2,3] has minimum-"right" start point.

Example 3:

Input: [ [1,4], [2,3], [3,4] ]

Output: [-1, 2, -1]

Explanation: There is no satisfied "right" interval for [1,4] and [3,4].
For [2,3], the interval [3,4] has minimum-"right" start point.

如果做过前面类似的有关intervals的题目,那么做这一题就比较简单的,很容易想到先排序,再遍历完成。

思路:

首先,根据题意要求,最后是要输出的是对应的interval的index,所以需要新构造一个数组int[][3]={start,end,index}(实际上end是不需要存储的,也不需要参与排序,在后面的代码2中可以看到这一点),前两个参数就是原来的开始和结束,第三个参数保存的是原来的该interval的位置(当然你构造一个类也可以,但是new大量的类的效率就会大打折扣)。

接下来,按照start升序排序,相同的start按照index升序排序(非常关键)。

然后,新建一个结果数组int[] result。遍历整个数组,找到当前元素(current)的end,然后使用循环找到后面的第一个new.start>=current.end的元素(new),将该元素的index值(new.index)写在当前result的对应位置,result[current.index]=new.index;如果循环结束都没有找到,result[current.index]=-1;以此类推,直到遍历完所有的元素,返回result即可。(如果使用数组的话,上面的start end index 分布为int[0] int[1] int[2]

代码如下,复杂度大约是O(nlogn)+O(n^2),事实上,是不可能达到理论上界的,因为第二项其实应该是个较大系数的O(n),所以猜测真实时间要稍稍大于nlogn的数量级,在nlogn和N^2的数量级之间:



/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class Solution {
    public int[] findRightInterval(Interval[] intervals) {
        int[] nResults = new int[intervals.length];
        // init results array
        for (int i = 0; i < nResults.length; i++) {
            nResults[i] = -1;
        }
        // init intervals array
        int[][] nIntervalsWithIndex = new int[intervals.length][3];
        for (int i = 0; i < nIntervalsWithIndex.length; i++) {
            nIntervalsWithIndex[i][0] = intervals[i].start;
            nIntervalsWithIndex[i][1] = intervals[i].end;
            nIntervalsWithIndex[i][2] = i;
        }
        Arrays.sort(nIntervalsWithIndex, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                if (o1[0] == o2[0]) {
                    return o1[2] - o2[2];
                } else {
                    return o1[0] - o2[0];
                }
            }
        });
        for (int i = 0; i < nIntervalsWithIndex.length; i++) {
            int nOriIndex = nIntervalsWithIndex[i][2];
            int nCurEnd = nIntervalsWithIndex[i][1];
            int nCurIndex = i;
            while (nCurIndex + 1 < nIntervalsWithIndex.length) {
                nCurIndex++;
                if (nIntervalsWithIndex[nCurIndex][0] >= nCurEnd) {
                    nResults[nOriIndex] = nIntervalsWithIndex[nCurIndex][2];
                    break;
                }
            }

        }
        return nResults;
    }
}

事实上,在上面的内存循环中,我们遍历了当前元素后面的元素。由于该内容其实是已经排好序的,而且我们只需要找到指定元素,这里显然是可以优化的,比如:可以考虑使用二分查找。因此,我们可以使用treeMap来存储数据,它默认按照key排序排列,而且treeMap的检索效率为O(logn)。

代码如下,新的代码复杂度为O(nlogn),实际时间消耗大约为2nlogn:

/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
import java.util.Map.Entry;
public class Solution {
    public int[] findRightInterval(Interval[] intervals) {
        int[] nResults = new int[intervals.length];
        TreeMap<Integer, Integer> tm = new TreeMap<>();
        for (int i = 0; i < intervals.length; i++) {
            tm.put(intervals[i].start, i);
        }
        for (int i = 0; i < intervals.length; i++) {
            Entry<Integer, Integer> e = tm.ceilingEntry(intervals[i].end);
            nResults[i] = e == null ? -1 : e.getValue();
        }
        return nResults;
    }
}



代码如下,复杂度大约是O(nlogn)+O(n^2),事实上,是不可能达到理论上界的,因为第二项其实应该是个较大系数的O(n),所有猜测真实时间稍大于nlogn:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值