题解
小 R 有n个集合,每个集合中的元素都是唯一的且互不相同。她希望通过随机选择两个集合,并计算它们的并集大小,来求出并集大小的期望值。结果需要保留两位小数。题目保证输入至少有两个集合。
问题分析
要计算随机选择两个集合的并集大小的期望值,关键在于确定每个元素在这两个集合的并集中出现的概率。具体步骤如下:
-
元素出现次数统计:
- 首先统计每个元素在所有集合中出现的次数。即,元素
x出现于v个不同的集合中。
- 首先统计每个元素在所有集合中出现的次数。即,元素
-
计算每个元素在并集中出现的概率:
-
对于一个元素
x,它至少出现在所选的两个集合中的一个的概率,可以通过以下公式计算: -
x不出现在两个集合中的概率为:其中,(\binom{n}{2})表示从
n个集合中选取两个集合的组合数。 -
因此,
x出现在并集中的概率为:
-
-
计算期望值:
- 期望值为所有元素在并集中出现概率的总和,即:
- 期望值为所有元素在并集中出现概率的总和,即:
-
结果格式化:
- 最终的期望值需要保留两位小数。
代码解析
from collections import Counter
def solution(n: int, st: list) -> str:
# 统计所有元素在所有集合中出现的次数
cnt = Counter([i for s in st for i in s])
res = 0
for k, v in cnt.items():
# 对于每个元素,计算其出现在并集中的概率,并累加到结果中
res += n * (n - 1) - (n - v) * (n - v - 1)
# 计算期望值并格式化为两位小数
return "{:.2f}".format(res / (n * (n - 1)))
if __name__ == '__main__':
print(solution(2, [[1, 2], [1, 3, 5]]) == '4.00') # 输出: True
print(solution(3, [[1, 4], [2, 5], [3, 6, 7]]) == '4.67') # 输出: True
print(solution(2, [[10, 20, 30], [10, 30, 50, 70]]) == '5.00') # 输出: True
时间复杂度分析
- 元素计数:扁平化所有集合的元素并进行计数,时间复杂度为 (O(m)),其中
m是所有集合中元素的总数。 - 期望值计算:遍历所有唯一元素,时间复杂度为 (O(k)),其中
k是唯一元素的数量。 - 总体时间复杂度:(O(m + k)),在最坏情况下,
k与m线性相关。
空间复杂度分析
- 使用了
Counter来存储元素的出现次数,空间复杂度为 (O(k))。