AI刷题-小c的mex查询 | 青训营笔记

101 阅读3分钟

问题描述

小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]

问题分析

我们需要模拟一个空集的增量操作,并在每次操作后输出当前集合的 mexmex 是集合中最小的未出现的非负整数。通过处理多个区间添加操作后,得出每次操作后的 mex 值。

关键概念:

  1. mex:即集合中最小的非负整数,不在集合中的最小整数。例如:

    • 集合 {0, 1, 2}mex 是 3,因为 0, 1, 2 都在集合中,最小的未出现的非负整数是 3。
    • 集合 {1, 2, 3}mex 是 0,因为 0 没有出现在集合中。
  2. 每次操作将一个区间 [l, r] 的整数加入集合,之后计算并输出当前的 mex

思路分析

  1. 增量添加:每次操作给定一个区间 [l, r],要将该区间内的所有整数添加到集合中。如果使用普通集合或者列表来表示,增加元素是简单的,但计算 mex 可能需要遍历集合中的所有元素来寻找最小的缺失数字,这样可能效率较低。

  2. 效率优化:为了优化每次操作的 mex 计算,我们可以使用以下方法:

    • 利用一个布尔数组或集合来记录当前集合中所有的整数。
    • 使用一个变量 mex_value 来追踪当前的 mex。当添加新元素时,只需更新 mex_value,如果 mex_value 被添加到集合中,那么 mex_value 就增加,直到找到下一个缺失的数字。
  3. 动态更新 mex:每次区间添加后,我们不需要重新扫描整个集合来计算 mex,而是通过从当前的 mex_value 开始检查,如果该数字已经存在集合中,则继续更新 mex_value

解题步骤

  1. 初始化一个空的集合 smex_value

  2. 对于每个查询 [l, r]

    • 将区间 [l, r] 内的数字添加到集合 s 中。
    • 更新 mex_value,如果 mex_value 已经在集合中,则递增 mex_value,直到找到一个不在集合中的 mex
  3. 每次操作后,输出当前的 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)。