【发布时间】:2019-10-17 22:49:48
【问题描述】:
我们设置了{1, 2, 3, ...,n} 个数字。我们希望生成这些数字的长度为 m 的排列,每个数字最多重复 k 次。
如果我们假设n=5, k=2, m=3,那么我们可以收到:{3,3,1},但不是{3, 3, 3},因为第二个例子中的3恰好是输出的三倍,大于k。
有没有一种快速统一生成这种排列的方法?
我尝试了两种不同的解决方案。
第一:
1) 产生带有重复的随机排列,有n^m 不同的排列。
2) 检查这是否是一个正确的排列(如果它不包含超过k 乘以相同的数字
3) 如果是,则返回,否则转到 1)
Python sn-p:
import numba
import numpy as np
@numba.jit(nopython=True)
def gen_sequence1(n, k, m):
result = np.random.randint(0, n, (1, m))[0]
while not is_correct(result, k):
result = np.random.randint(0, n, (1, m))[0]
return result
@numba.jit(nopython=True)
def most_frequent(iter):
return np.bincount(iter).max()
@numba.jit(nopython=True)
def is_correct(pruf, k):
return most_frequent(pruf) <= k
第二种方法:
生成随机整数,仅当它在k 次之前没有出现时才将其添加到序列中。这些词的优化版本如下所示(用 Python 编写)。
Python sn-p:
def gen_seq(n, d, m):
choices = list(range(n))
degrees = [0] * n
result = []
k = n - 1
for i in range(m):
rand = np.random.randint(0, k)
result.append(choices[rand])
degrees[choices[rand]] += 1
if degrees[choices[rand]] == d:
choices[rand], choices[k] = choices[k], choices[rand]
k -= 1
return result
问题是第一种方法对于n=30, m=28, d=1 非常慢,它需要10^9 次来生成序列,这很明显。
第二个是没有产生统一的排列(有些比其他的概率更大)。
您有什么想法可以快速统一地生成这样的序列吗?
【问题讨论】:
-
不必在 Python 中。我正在寻找更多的想法,而不是程序。
标签: algorithm random language-agnostic permutation uniform