生成部分有序的随机数字列表

时间:2014-04-22 03:20:52

标签: java c++ algorithm sorting

我想生成一个大小为500的随机数列表,其中列表正好是30%排序(我知道如何生成至少30%排序的列表),但这不是我想要的,我该怎么做生成一个“完全”30%的文件?我被困了,怎么办呢?

这是准确的措辞 “对于各种类型,你应该构建三种不同的文件:每个大小的顺序,按顺序排列,最后一个按顺序排列30%的密钥。后一个文件不应该包含排序为30%的文件完成,而是在30%的密钥相对于彼此正确放置但不一定是连续的文件中。

2 个答案:

答案 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的运行时间从这里看起来略显过高。