小R的并集大小期望计算 | 豆包MarsCode AI刷题

62 阅读4分钟

伴学笔记:求两个集合并集大小的期望值

一、题目分析

小R有 n 个集合,每个集合中的元素都是唯一的且互不相同。小R希望通过随机选择两个集合,并计算它们的并集大小,来求出这个并集大小的期望值。要求最终结果保留两位小数。

输入格式

  • n:集合的数量。
  • st:包含 n 个集合的列表,其中每个集合 st[i] 是一个整数列表,代表该集合中的元素。

输出格式

  • 返回一个字符串,表示随机选择两个集合的并集大小的期望值,保留两位小数。

二、期望值计算

为了求出两个集合并集大小的期望值,可以从以下角度分析:

  1. 并集大小的期望:对于任意两个集合,求其并集大小相当于计算这两个集合中不同元素的数量。我们通过统计每个元素在多个集合中出现的频次,来计算它在并集中的概率。
  2. 元素出现次数的影响:如果一个元素在多个集合中出现,则它对并集大小的影响较小,反之,如果一个元素仅出现在少数几个集合中,则它对并集的贡献较大。
  3. 概率计算:对于每个元素,我们可以通过计算它出现在两个随机选择的集合中的概率,来估计它对并集大小的贡献。

三、解题思路

  1. 统计元素的出现次数:我们首先统计每个元素在所有集合中出现的次数。这可以通过一个字典 freq 来完成,键为元素,值为元素在集合中出现的次数。
  2. 计算期望值:对于每个元素,计算它出现在两个集合中的概率,进而求出它对并集大小的贡献。最终将所有元素的贡献加起来,得到两个集合并集大小的期望值。
  3. 格式化输出:结果要求保留两位小数,因此需要在计算完期望值后格式化输出。

四、代码实现

from collections import defaultdict

def solution(n: int, st: list) -> str:
    # 统计每个元素出现的集合数
    freq = defaultdict(int)
    for s in st:
        for e in s:
            freq[e] += 1
    
    total_expected_union = 0.0  # 初始化期望并集大小
    denominator = n * (n - 1)  # 随机选两个集合的总可能数
    
    # 遍历每个元素,计算其在并集中的概率
    for k in freq.values():
        # 计算每个元素出现在并集中的概率
        probability = 1 - ((n - k) * (n - k - 1)) / denominator
        total_expected_union += probability
    
    # 格式化结果保留两位小数
    return "{0:.2f}".format(total_expected_union)

# 测试用例
if __name__ == '__main__':
    print(solution(2, [[1, 2], [1, 3, 5]]) == '4.00')
    print(solution(3, [[1, 4], [2, 5], [3, 6, 7]]) == '4.67')
    print(solution(2, [[10, 20, 30], [10, 30, 50, 70]]) == '5.00')

五、代码解释

  1. 统计元素出现次数: 使用 defaultdict(int) 来存储元素的出现频次。对于每个集合中的元素,我们将其在字典中对应的值加一,表示该元素在当前集合中出现。

  2. 计算期望值: 对于每个元素 k,它出现 freq[k] 次。我们需要计算这个元素出现在随机选择的两个集合中的概率。该概率为:

    P(element appears in the union)=1−(n−k)×(n−k−1)n×(n−1)P(\text{element appears in the union}) = 1 - \frac{(n - k) \times (n - k - 1)}{n \times (n - 1)}

    其中,n 为集合的总数,k 为当前元素的出现次数。分子部分计算了这个元素不出现在两个集合中的概率。

  3. 格式化输出: 通过 "{0:.2f}".format(total_expected_union) 来确保结果保留两位小数。

六、复杂度分析

  • 时间复杂度:O(n * m),其中 n 为集合的个数,m 为平均每个集合的元素个数。我们需要遍历每个集合中的每个元素来统计其出现频次。
  • 空间复杂度:O(k),其中 k 为元素的种类数。我们需要一个字典来存储每个元素的出现次数。

七、测试用例

  1. 输入

    solution(2, [[1, 2], [1, 3, 5]])
    

    输出

    '4.00'
    
  2. 输入

    solution(3, [[1, 4], [2, 5], [3, 6, 7]])
    

    输出

    '4.67'
    
  3. 输入

    solution(2, [[10, 20, 30], [10, 30, 50, 70]])
    

    输出

    '5.00'
    

八、总结

通过这个问题,我们学到了如何利用元素频率来计算期望值,尤其是在处理集合并集相关问题时,如何计算元素的贡献概率。希望大家能理解期望值的概念和概率计算方法,并能灵活运用于其他类似问题中。