我想生成一个大小为500的随机数列表,其中列表正好是30%排序(我知道如何生成至少30%排序的列表),但这不是我想要的,我该怎么做生成一个“完全”30%的文件?我被困了,怎么办呢?
这是准确的措辞 “对于各种类型,你应该构建三种不同的文件:每个大小的顺序,按顺序排列,最后一个按顺序排列30%的密钥。后一个文件不应该包含排序为30%的文件完成,而是在30%的密钥相对于彼此正确放置但不一定是连续的文件中。
答案 0 :(得分:1)
我可以看到有两个主要观点:百分比排序:
只是元素数量不合适。
一旦应该能够通过排序得到估计的%排序,然后迭代它,并保持每个元素与所需百分比相同的概率,否则用随机剩余元素交换(所以,如果我们想要30%排序,我们保持元素相同,概率为30%,并将其换成70%)。
如果需要一个确切的数字,可以使用上述结果并(智能地)交换随机元素,直到获得所需的百分比。
inversions的数量。
反转是序列的一对位置,这些位置上的元素超出了它们的自然顺序。
一个想法是先对它进行排序,然后交换使我们接近所需百分比的随机元素,直到我们到达那里。
只有交换元素才能让我们更接近理想的结果(至少这样做很有效)。
一种非常强力的方法是计算每对交换所引起的反转次数的变化,然后选择一个让我们更接近目标的随机数。
另一个想法是只生成随机对并计算反转次数,直到我们找到一个让我们更接近的对象。
第三种选择是选择一个随机元素。如果它大于元素的一半,请尝试向左移动(理想情况下增加反转次数)。如果它更小,请尝试向右移动。在尝试向左/向右移动时,我们可以寻找一个更小/更大的元素(分别)来交换它并计算反转的变化(我们只需要在计算反转变化时考虑交换元素之间的元素)
起初我们可能只是随意交换元素,因为我们可能倾向于更多的反转。
如果百分比高于50%,我们也可以从反向数组开始,即100%未分类。
答案 1 :(得分:0)
有一对一的对应关系,将排列映射到{0} x {0,1} x {0,1,2} x ... x {0,1,... n - 1},其中,codomain中元组的第j个元素是涉及位置j和i <1的元素的反转次数。学家有鉴于此,问题是对共同域的随机元素进行抽样,该元素与所需的反演次数相加。
这是针对此问题的Gibbs sampling实例。初始化一个元组求和到所需的排列数。重复选择两个不同的指数,并在具有相同总和的所有可能性之间均匀随机化。当你厌倦了等待时停止(分布收敛于统一但永远不会到达那里;也许明天我会找出一个Propp - Wilson样式的技术用于精确样本)。
在Python中(未经测试):
import random
def gibbs(n, target):
perm = [0] * n
for i in range(n):
perm[i] = min(target, i)
target -= i
assert target == 0
while ???:
i = random.randrange(n)
j = random.randrange(n)
if i == j: continue
total = perm[i] + perm[j]
perm[i] = random.randrange(max(total - j, 0), i + 1)
perm[j] = total - perm[i]
for j in range(n):
perm[j] = j - perm[j]
for i in range(j):
if perm[i] >= perm[j]: perm[i] += 1
return perm
也可以通过动态编程和条件概率获得精确的样本,但500的运行时间从这里看起来略显过高。