通过万岁!!!
- 题目:就是给你一个区间数组,然后找到每个区间的右侧最近的区间,并返回每个区间对应的右侧最近区间的下标数组。区间的开始位置不会重复。
- 题目有点绕,我们举个例子,就是一个区间数组,我们看第i个位置,他的区间结束为end,那么我们找一个区间,是从大于end开始的,并且是距离end最近的,我们找的这个区间,还是要在这个区间数组中。
- 思路:
- 首先,我们要对这个区间数组进行排序,就是对开始位置进行排序。这样方便我们接下来查找,我们只需要拿到end以后,在这个排好序的数组中找到第一个大于end的数,这个数就是右侧区间的开始位置,然后我们在找到他在数组中的下标即可。
- 但是我们发现,我们找到这个开始位置以后,还需要再找他的开始位置,比较麻烦,所以我们直接将开始位置和他的下标进行一个封装,构建一个数组,每一行都是[开始位置,这个区间在数组中的下标]。这个数组很好创建,就是遍历一下给的区间数组即可。
- 接下来就是对这个数组的第一列进行排序,这样我们就把开始位置进行了排序。并且他的下标紧随其后,就在这个数组的第二列。
- 然后就是对开始位置进行二分查找即可。注意,这里需要找到相等,或者第一个大于目标值的,实在找不到就是-1。这个跟之前的蓝桥杯题目-分巧克力有相似,那个是找到第一个比target小的数。
- 技巧:二维数组排序,二分查找找到第一个大于target数的位置。
java代码
class Solution {
public int[] findRightInterval(int[][] intervals) {
// 看左边有没有比右边大的
int len = intervals.length;
int[] ans = new int[len];
int[][] map = new int[len][2];
for (int i = 0; i < len; i++) {
map[i][0] = intervals[i][0];
map[i][1] = i;
}
// 对第0维度进行排序
Arrays.sort(map, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
if (o1[0] == o2[0]) {
return o1[1] - o2[1];
}
return o1[0] - o2[0];
}
});
int l, r, mid;
for (int i = 0; i < len; i++) {
ans[i] = -1;
// 二分查找,找到第一个比他大的
l = 0;
r = len - 1;
while (l <= r) {
mid = (l + r) / 2;
if (map[mid][0] == intervals[i][1]) {
ans[i] = map[mid][1];// 拿到下标
break;
} else if (map[mid][0] > intervals[i][1]) {
r = mid - 1;
} else {
l = mid + 1;
}
}
if (ans[i] != -1) {
continue;
}
if (l < len && map[l][0] > intervals[i][1])
ans[i] = map[l][1];// 第一个比他大的
}
return ans;
}
}
- 总结:题目比较有意思,这个题有两个难点,一个是对二分查找的一个提升,就是找到比他大的数,或者比他小的数。第二个就是二维数组的排序。