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

Raphael Liu Lv10

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

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

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

示例 1:

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

示例 2:

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

提示:

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

方法一:差分数组

思路与算法

为了判断某个区域内所有整数都被覆盖,我们需要对每个整数 x 计算覆盖该整数的区间数量,记作 cnt}_x。

朴素的做法是,遍历 ranges 中的所有区间 [l, r],将区间内每个整数的 cnt 值加上 1。遍历结束后,检查 [\textit{left},\textit{right}] 内的每个整数的 cnt 值是否均大于 0,是则返回 true,否则返回 false。

记 ranges 的长度为 n,需要计算的区间范围为 l,则上述做法的时间复杂度为 O(n\cdot l)。

下面介绍复杂度为 O(n + l) 的做法。我们可以用差分数组 diff 维护相邻两个整数的被覆盖区间数量变化量,其中 diff}[i] 对应覆盖整数 i 的区间数量相对于覆盖 i - 1 的区间数量变化量。这样,当遍历到闭区间 [l, r] 时,l 相对于 l - 1 被覆盖区间数量多 1,r + 1 相对于 r 被覆盖区间数量少 1。对应到差分数组上,我们需要将 diff}[l] 加上 1,并将 diff}[r + 1] 减去 1。

在维护完差分数组 diff 后,我们遍历 diff 求前缀和得出覆盖每个整数的区间数量。下标 i 对应的被覆盖区间数量即为初始数量 0 加上 [1, i] 闭区间的变化量之和。在计算被覆盖区间数量的同时,我们可以一并判断 [\textit{left}, \textit{right}] 闭区间内的所有整数是否都被覆盖。

代码

[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
bool isCovered(vector<vector<int>>& ranges, int left, int right) {
vector<int> diff(52, 0); // 差分数组
for (auto&& range: ranges) {
++diff[range[0]];
--diff[range[1]+1];
}
// 前缀和
int curr = 0;
for (int i = 1; i <= 50; ++i) {
curr += diff[i];
if (i >= left && i <= right && curr <= 0) {
return false;
}
}
return true;
}
};
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public boolean isCovered(int[][] ranges, int left, int right) {
int[] diff = new int[52]; // 差分数组
for (int[] range : ranges) {
++diff[range[0]];
--diff[range[1] + 1];
}
// 前缀和
int curr = 0;
for (int i = 1; i <= 50; ++i) {
curr += diff[i];
if (i >= left && i <= right && curr <= 0) {
return false;
}
}
return true;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Solution {
public bool IsCovered(int[][] ranges, int left, int right) {
int[] diff = new int[52]; // 差分数组
foreach (int[] range in ranges) {
++diff[range[0]];
--diff[range[1] + 1];
}
// 前缀和
int curr = 0;
for (int i = 1; i <= 50; ++i) {
curr += diff[i];
if (i >= left && i <= right && curr <= 0) {
return false;
}
}
return true;
}
}
[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def isCovered(self, ranges: List[List[int]], left: int, right: int) -> bool:
diff = [0] * 52 # 差分数组
for l, r in ranges:
diff[l] += 1
diff[r+1] -= 1
# 前缀和
curr = 0
for i in range(1, 51):
curr += diff[i]
if left <= i <= right and curr <= 0:
return False
return True
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var isCovered = function(ranges, left, right) {
const diff = new Array(52).fill(0); // 差分数组
for (const [l, r] of ranges) {
diff[l]++;
diff[r + 1]--;
}
// 前缀和
let curr = 0;
for (let i = 1; i < 51; i++) {
curr += diff[i];
if (left <= i && i <= right && curr <= 0) {
return false;
}
}
return true;
};
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func isCovered(ranges [][]int, left, right int) bool {
diff := [52]int{} // 差分数组
for _, r := range ranges {
diff[r[0]]++
diff[r[1]+1]--
}
cnt := 0 // 前缀和
for i := 1; i <= 50; i++ {
cnt += diff[i]
if cnt <= 0 && left <= i && i <= right {
return false
}
}
return true
}
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool isCovered(int** ranges, int rangesSize, int* rangesColSize, int left, int right) {
int diff[52]; // 差分数组
memset(diff, 0, sizeof(diff));
for (int i = 0; i < rangesSize; i++) {
++diff[ranges[i][0]];
--diff[ranges[i][1] + 1];
}
// 前缀和
int curr = 0;
for (int i = 1; i <= 50; ++i) {
curr += diff[i];
if (i >= left && i <= right && curr <= 0) {
return false;
}
}
return true;
}

复杂度分析

  • 时间复杂度:O(n + l),其中 n 为 ranges 的长度,l 为 diff 的长度。初始化 diff 数组的时间复杂度为 O(l),遍历 ranges 更新差分数组的时间复杂度为 O(n),求解前缀和并判断是否完全覆盖的时间复杂度为 O(l)。

  • 空间复杂度:O(l),即为 diff 的长度。

 Comments
On this page
1893-检查是否区域内所有整数都被覆盖