问题描述
小C拿到了一个空集。她准备进行以下操作:将 [l,r] 区间的每个整数添加进集合。
每次操作后,输出当前集合的 mex。定义集合的 mex 为:集合中最小的未出现的非负整数。
测试样例
样例1:
输入:
q = 4,queries = [[1, 3], [7, 8], [0, 5], [3, 6]]
输出:[0, 0, 6, 9]
样例2:
输入:
q = 3,queries = [[0, 2], [3, 4], [6, 10]]
输出:[3, 5, 5]
样例3:
输入:
q = 2,queries = [[2, 5], [7, 9]]
输出:[0, 0]
问题分析
我们需要模拟一个空集的增量操作,并在每次操作后输出当前集合的 mex。mex 是集合中最小的未出现的非负整数。通过处理多个区间添加操作后,得出每次操作后的 mex 值。
关键概念:
-
mex:即集合中最小的非负整数,不在集合中的最小整数。例如:- 集合
{0, 1, 2}的mex是 3,因为0, 1, 2都在集合中,最小的未出现的非负整数是 3。 - 集合
{1, 2, 3}的mex是 0,因为0没有出现在集合中。
- 集合
-
每次操作将一个区间
[l, r]的整数加入集合,之后计算并输出当前的mex。
思路分析
-
增量添加:每次操作给定一个区间
[l, r],要将该区间内的所有整数添加到集合中。如果使用普通集合或者列表来表示,增加元素是简单的,但计算mex可能需要遍历集合中的所有元素来寻找最小的缺失数字,这样可能效率较低。 -
效率优化:为了优化每次操作的
mex计算,我们可以使用以下方法:- 利用一个布尔数组或集合来记录当前集合中所有的整数。
- 使用一个变量
mex_value来追踪当前的mex。当添加新元素时,只需更新mex_value,如果mex_value被添加到集合中,那么mex_value就增加,直到找到下一个缺失的数字。
-
动态更新
mex:每次区间添加后,我们不需要重新扫描整个集合来计算mex,而是通过从当前的mex_value开始检查,如果该数字已经存在集合中,则继续更新mex_value。
解题步骤
-
初始化一个空的集合
s和mex_value。 -
对于每个查询
[l, r]:- 将区间
[l, r]内的数字添加到集合s中。 - 更新
mex_value,如果mex_value已经在集合中,则递增mex_value,直到找到一个不在集合中的mex。
- 将区间
-
每次操作后,输出当前的
mex_value。
代码实现
python
Copy code
def find_mex(q, queries):
s = set() # 用一个集合来记录已添加的数字
mex_value = 0 # 初始化mex值
result = [] # 存储每次操作后的mex结果
for query in queries:
l, r = query
# 将区间[l, r]的所有数字加入集合
for num in range(l, r + 1):
s.add(num)
# 更新mex值
while mex_value in s:
mex_value += 1
# 保存当前mex值
result.append(mex_value)
return result
复杂度分析
-
时间复杂度:
- 对于每个查询
[l, r],我们需要向集合中添加r - l + 1个元素。因此,对于每个查询的时间复杂度是O(r - l + 1)。 - 由于
mex_value仅在需要时更新,查找和更新mex_value的时间复杂度是常数级别的 O(1),因此可以忽略。 - 总体时间复杂度是 O(n),其中 n 是所有查询中数字总个数的累积。
- 对于每个查询
-
空间复杂度:
- 主要空间消耗是集合
s,用于存储所有加入的数字。最坏情况下,集合的大小是O(max(r) - min(l) + 1),即区间内所有数字都被加入时,空间复杂度是 O(n)。
- 主要空间消耗是集合