生存一个随机数列,但要求总和固定常数

如何用生成一个随机数列,每个数的随机范围在(j, k)之间,需要生成n个,总和固定住,比如m

这个n可能会比较大,我试过递归的方式,但是失败了。

对效率没有要求

阅读 3.8k
2 个回答

首先,你必须要m/n(j,k)范围内才可能

还有,你没有提出随机性的要求,为了保障高效,可以做一些特殊处理,比如其实真正随机生成了n/2K1数字,然后找到对应的另外n/2K2 ,使得 k1+k2 = 2m/n

至于生成的随机数在 (j,k) 范围内,pythonrandom 模块直接就有方法,比如
random.uniform(a,b) 就是随机生成 [a,b] 范围内的浮点数,random.randint(a, b)就是随机生成 [a,b] 范围内的整数。

此外生成了n个数后,再用随机扑克排序方法,最后输出效果更好。

我们先假定几个数,j=1, k=10, m=10, n=4

我这里是允许有多个重复值出现。
首先我们要保证n个数能生成出来,我们要求第一个数不能太大,比如第一个出来了 7,后面的数就出不来了,所以我们要求第一个随机数要小于等于 m-(n-1)*j
每生成一个数我们都可以调整 k 的值了,过大的 k 已经没有意义了,让它等于 m-已生成数之和-(n-1-当前个数)*j
在剩余的数字个数乘 k 将要不满足剩余和的时候,修正一下 j 的值,剩余和与个数取平均值,jk分别为平均值的两端,继续在这个范围内取随机数。
这样修正 j 的值就是有点过早。
简单的写一个示例,需要更多的要求可以再做修改:

def fun_a(j=0, k=10, m=10, n=4):
    if m > n * k or m < n * j:
        print 'can not generate the num list.'
        return
    data = []
    k = k if k <= m else m
    for i in range(n):
        # 这里修正 j 的值
        if (n - i - 1) * k < m - sum(data):
            j = 2 * ((m - sum(data)) / (n - i)) - k

        if i == n - 1:
            tmp = k
        else:
            tmp = random.randint(j, k)
            # if i == 0:
            while tmp > m - (n-1-i) * j - sum(data):
                tmp = random.randint(j, k)
        data.append(tmp)
        
        tmp_k = m - sum(data) - (n - 2 - i)*j
        k = tmp_k if k > tmp_k else k

    return data
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题