题目来源:https://leetcode-cn.com/problems/check-if-all-the-integers-in-a-range-are-covered/
大致题意:
给定一个二维数组,其中每个以为一维数组为一个闭区间。再给定一个left和right,判断left到right之间的所有数是否在之前给定的区间中(区间可能有重叠)
思路
暴力
遍历每个区间,然后给区间内所有数做标记。
之后从left遍历到right,查看是否所有数都被标记。
排序
- 先对区间按照左边界升序排序
- 遍历所有区间,若left在当前区间中,left更改为当前区间右边界+1
- 若left大于right,则说明所有数都在曲建忠,返回true;反之,返回false
代码:
public boolean isCovered(int[][] ranges, int left, int right) {
boolean ans = true
// 排序
Arrays.sort(ranges, (a1, a2) -> a1[0] > a2[0]);
for (int[] range : ranges) {
if (range[0]<= left && left <= range[1]) // 判断left是否在当前区间
left = range[1] + 1;
}
ans = left > right;
return ans;
}
差分
使用差分对区间数进行标记。
- 已知所有区间在[1, 50]内,所以创建一个适当大小(52,考虑到索引0和索引51)的diff数组。
- 遍历所有区间,区间左边界对应的diff加1,右边界+1的位置对应的diff-1
- 为什么这样做?
- 因为这样,可以在从前往后遍历时,使用一个score来记录遍历位置的diff和,那么所有在给定区间的数(数即为对应的diff索引)的score应当是大于0的。那么也就是,不在区间的数,其score不超过0。
- 为什么在区间的数,其score大于0?
- 因为,若当前数num,在区间[x, y]中,那么在遍历到x的时候,score已经+1,而直到y score的值都不会减,定然是大于0。若中间穿插其他区间,那么穿插区间要么都在num左边(这样score已经+1又-1,score不受影响),要么穿插区间覆盖num(这样score在穿插区间左边界+1,还未到右边界,不用-1,score更大,不影响结果),要么穿插区间在num右边(这样score的改变当然和当前位置无关)
因为给定区间在[1, 50],所以接下来再遍历该区间。若当前遍历的数在所求区间(left至right)中,且其差分分值小于0,那么其不在之前的所有区间中,直接返回false。
public boolean isCovered(int[][] ranges, int left, int right) {
boolean ans = true;
int[] diff = new int[52];
for (int[] range : ranges) { // 差分标记
diff[range[0]]++;
diff[range[1]+1]--;
}
int score = 0;
for (int i = 1; i <= 50; i++) {
score += diff[i]; // 当前数的差分分值
if (left <= i && i <= right && score <= 0) {
// 若当前数在所求区间中,且差分分值小于0
ans = false;
break;
}
}
return ans;
}