leetcode
leetcode 2701 ~ 2750
检查是否区域内所有整数都被覆盖

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

难度:

标签:

题目描述

You are given a 2D integer array ranges and two integers left and right. Each ranges[i] = [starti, endi] represents an inclusive interval between starti and endi.

Return true if each integer in the inclusive range [left, right] is covered by at least one interval in ranges. Return false otherwise.

An integer x is covered by an interval ranges[i] = [starti, endi] if starti <= x <= endi.

 

Example 1:

Input: ranges = [[1,2],[3,4],[5,6]], left = 2, right = 5
Output: true
Explanation: Every integer between 2 and 5 is covered:
- 2 is covered by the first range.
- 3 and 4 are covered by the second range.
- 5 is covered by the third range.

Example 2:

Input: ranges = [[1,10],[10,20]], left = 21, right = 21
Output: false
Explanation: 21 is not covered by any range.

 

Constraints:

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

代码结果

运行时间: 24 ms, 内存: 16.0 MB


/*
 * 思路:
 * 1. 使用流(Stream)来处理区间。
 * 2. 使用一个 HashSet 来存储所有被覆盖的整数。
 * 3. 遍历 left 到 right 的每个整数,检查它们是否都在 HashSet 中。
 */
import java.util.HashSet;
import java.util.Set;
import java.util.stream.IntStream;

public class Solution {
    public boolean isCovered(int[][] ranges, int left, int right) {
        Set<Integer> covered = new HashSet<>();
        for (int[] range : ranges) {
            IntStream.rangeClosed(range[0], range[1]).forEach(covered::add);
        }
        return IntStream.rangeClosed(left, right).allMatch(covered::contains);
    }
}

解释

方法:

该题解采用了标记数组的方法来解决问题。首先,创建一个长度为51的数组tmp(考虑到题目中的整数范围可能从1到50),用于记录特定整数是否被覆盖。对于每个区间[starti, endi],遍历该区间中的所有整数,并将对应的tmp数组中的值设为1,表示该整数已被覆盖。接着,遍历从left到right的所有整数,检查这些整数是否都在tmp数组中被标记为1(即被覆盖)。如果存在未被覆盖的整数,则直接返回False。如果所有整数都被覆盖,则返回True。

时间复杂度:

O(N+M)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么选择使用长度为51的数组tmp来记录覆盖状态而不是其他数据结构,如哈希表或集合?
在这个特定的问题中,我们需要频繁地检查和更新每个整数是否被覆盖的状态,数组通过其索引直接访问元素提供了O(1)的时间复杂度,这使得操作非常高效。而使用哈希表或集合虽然也可以达到类似的效果,但可能涉及更多的内存开销和计算开销(如哈希函数的计算)。考虑到整数范围有限(仅1到50),使用固定大小的数组是简单且高效的解决方案。
🦆
在创建tmp数组时,为何初始化长度为51,而不是基于left和right的值来调整数组的大小?
数组tmp的长度设为51是因为题目描述中提到整数的范围可能是1到50,因此为了简化索引操作(直接使用整数值作为索引而不需要额外的映射),数组的大小被固定为51(索引0不使用,1至50正好对应整数1到50的覆盖状态)。此外,这样的处理避免了基于left和right动态调整数组大小的复杂性,使得代码更为简洁和通用。
🦆
如果ranges中的区间非常大,比如[starti, endi]覆盖了大量不在[left, right]区间内的整数,这种方法的空间效率如何?
如果ranges包含的区间远大于[left, right],尽管这种方法在处理大范围区间时可能会导致对不必要的整数也进行覆盖检查,但由于数组tmp的大小固定为51,空间复杂度保持为O(1),即常数级别。因此,尽管可能存在一些不必要的覆盖检查,空间效率依然是高效的。对于这种情况,时间效率可能更受影响,因为需要遍历较大的区间来设置覆盖状态。

相关问题