力扣 1893. 检查是否区域内所有整数都被覆盖

题目说明

  • 给你一个二维整数数组 ranges 和两个整数 leftright 。每个 ranges[i] = [starti, endi] 表示一个从 startiendi闭区间

    如果闭区间 [left, right] 内每个整数都被 ranges至少一个 区间覆盖,那么请你返回 true ,否则返回 false

    已知区间 ranges[i] = [starti, endi] ,如果整数 x 满足 starti <= x <= endi ,那么我们称整数x 被覆盖了。

  • 提示:

    • 1 <= ranges.length <= 50
    • 1 <= starti <= endi <= 50
    • 1 <= left <= right <= 50

示例

示例 1:

1
2
3
4
5
6
输入:ranges = [[1,2],[3,4],[5,6]], left = 2, right = 5
输出:true
解释:2 到 5 的每个整数都被覆盖了:
- 2 被第一个区间覆盖。
- 3 和 4 被第二个区间覆盖。
- 5 被第三个区间覆盖。

示例 2:

1
2
3
输入:ranges = [[1,10],[10,20]], left = 21, right = 21
输出:false
解释:21 没有被任何一个区间覆盖。

笔者理解

此题是一道数组算法问题,在力扣题库中被定义为简单题。

解法

当笔者阅读完此题后,发现本题用差分数组加前缀和最优,这道题的讲解,我首推这篇带图的讲解,通俗易懂,让我们来看看具体如何实现的吧。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
/*
* 差分数组
* 前缀和
*/
public boolean isCovered(int[][] ranges, int left, int right) {
int[] diff = new int [52];
// 将区间的起点标记为1,终点的后一位标记为-1,这样就可以囊括所有出现的数
// 在之后通过前缀和就可以轻松还原当前数是否出现过
for (int i = 0; i < ranges.length; i++) {
diff[ranges[i][0]]++;
diff[ranges[i][1] + 1]--;
}
// 前缀和数组,方便理解,其实可以在原数组上操作
int[] sum = new int [52];
for (int i = 1; i < 52; i++) {
sum[i] = sum[i - 1] + diff[i];
}

// 如果当前数小于等于0,说明这个数没出现过
for (; left <= right; left++) {
if (sum[left] <= 0) {
return false;
}
}
return true;
}
}

时间空间效率都还行,可见此解法还比较适合此题;

image.png

总结

本题是今天的每日一题,难度是为简单,感兴趣的朋友都可以去尝试一下,此题还有其他更多的解法,朋友们可以自己逐一尝试。