最容易想到的方法,使用两个vector装点数数组,最后再进行遍历比较,显然这个方法效率不高
动态规划方法
1. 使用和的分布计数代替生成组合
对于每个元素数组 arrayN 和 arrayM,我们通常会生成所有可能的和组合。这在大数据集下会产生大量中间结果,导致内存耗尽。为了解决这一问题,我们可以采用分布计数的方式来记录各个和出现的频次,而不生成具体的组合。
例如,如果 arrayN 中一个元素为 3,则所有和可以是 1, 2, 3。通过计数,我们可以得到每个和出现的次数,而不需要直接存储每个组合。
2. 动态更新和的分布计数
为每个数组分别维护一个计数字典 a_counts 和 b_counts。初始情况下,它们包含和为 0 的空组合。接下来:
- 遍历数组中的每个数
num。 - 对当前所有可能的和(在
a_counts中的和)逐一进行更新,每次将num拆分成所有可能的加和情况(例如1, 2,..., num)。 - 逐步累加到每个现有和,更新可能的新和及其出现频次。
示例:假设 arrayN = [3, 2]
- 初始化:
a_counts = {0: 1} - 处理
3:a_counts更新为{1: 1, 2: 1, 3: 1} - 处理
2:基于当前a_counts的和,生成{1+1, 1+2,...}的分布计数。
3. 计算满足条件的组合数
通过 a_counts 和 b_counts 得到 arrayN 和 arrayM 中可能和的分布后,下一步是计算满足条件的组合数:
- 设定
total为总的组合数,即a_counts和b_counts中所有组合的乘积。 - 遍历
a_counts和b_counts中的每一对和,若a_sum > b_sum,则此组合满足条件b < a,将该组合的频次积累到计数cnt中。
4. 计算概率并返回结果
最后,概率 ans 就是满足条件的组合数与总组合数的比值 cnt / total,再将结果四舍五入到三位小数输出。
def solution(n, m, arrayN, arrayM):
# Edit your code here
a_counts = {0: 1}
b_counts = {0: 1}
# 更新a_counts分布
for num in arrayN:
new_counts = {}
for val, count in a_counts.items():
for j in range(1, num + 1):
new_sum = val + j
if new_sum in new_counts:
new_counts[new_sum] += count
else:
new_counts[new_sum] = count
a_counts = new_counts
# 更新b_counts分布
for num in arrayM:
new_counts = {}
for val, count in b_counts.items():
for j in range(1, num + 1):
new_sum = val + j
if new_sum in new_counts:
new_counts[new_sum] += count
else:
new_counts[new_sum] = count
b_counts = new_counts
# 计算满足条件的组合数和总组合数
total = sum(a_count * b_count for a_count in a_counts.values() for b_count in b_counts.values())
cnt = sum(a_count * b_count for a_sum, a_count in a_counts.items() for b_sum, b_count in b_counts.items() if b_sum < a_sum)
# 返回概率,保留三位小数
ans = cnt / total
return round(ans, 3)
if __name__ == "__main__":
# Add your test cases here
print(solution(1, 3, [8], [2, 3, 4]) == 0.255)