要解决这个问题,需要计算 两个集合并集大小的期望值。这是一个数学和算法结合的问题,以下是具体的思路与实现步骤。
解题思路
1. 理解并集大小的计算
给定两个集合 AA 和 BB:
- 并集大小公式为: ∣A∪B∣=∣A∣+∣B∣−∣A∩B∣|A \cup B| = |A| + |B| - |A \cap B|
2. 随机选择两个集合
对于 nn 个集合,随机选择两个集合的组合有 (n2)=n(n−1)2\binom{n}{2} = \frac{n(n-1)}{2} 种。每种组合的并集大小需要计算一次。
3. 计算所有组合的并集大小
对于每对集合 (Ai,Aj)(A_i, A_j),计算其并集大小,并累计求和。
4. 计算期望
并集大小的期望公式为:
期望=所有并集大小的总和所有组合数\text{期望} = \frac{\text{所有并集大小的总和}}{\text{所有组合数}}
5. 结果保留两位小数
使用 Python 的 format 函数将结果格式化到两位小数。
算法实现
以下是基于上述思路的 Python 实现:
def union_expectation(n, sets):
from itertools import combinations
# 所有并集大小总和
total_union_size = 0
# 选择任意两个集合的组合
pairs = list(combinations(range(n), 2)) # 生成所有集合下标对 (i, j)
for i, j in pairs:
set1, set2 = sets[i], sets[j]
# 计算 |A ∪ B| = |A| + |B| - |A ∩ B|
union_size = len(set1) + len(set2) - len(set1 & set2)
total_union_size += union_size
# 计算所有组合数
total_combinations = len(pairs)
# 计算期望值
expectation = total_union_size / total_combinations
# 返回保留两位小数的结果
return f"{expectation:.2f}"
# 测试样例
print(union_expectation(2, [{1, 2}, {1, 3, 5}])) # 输出: '4.00'
print(union_expectation(3, [{1, 4}, {2, 5}, {3, 6, 7}])) # 输出: '4.67'
print(union_expectation(2, [{10, 20, 30}, {10, 30, 50, 70}])) # 输出: '5.00'
代码解析
-
输入处理
- 使用集合的交集
set1 & set2和大小len(set)快速计算并集大小。
- 使用集合的交集
-
组合生成
- 使用
itertools.combinations生成所有集合下标的两两组合,避免手动嵌套循环。
- 使用
-
期望计算
- 累加所有并集大小,再除以组合总数,得到平均值。
-
结果格式化
- 使用
f"{value:.2f}"将结果保留两位小数。
- 使用
测试与优化
时间复杂度
- 组合生成:O(n2)O(n^2)
- 并集计算:对于每对集合,集合操作时间复杂度与集合大小有关,设最大集合大小为 mm,复杂度为 O(m)O(m)。
- 总复杂度:O(n2⋅m)O(n^2 \cdot m)
可扩展性
- 如果集合数量 nn 或单个集合大小 mm 增大,可以通过优化集合操作或引入分布式计算处理超大规模数据。