DI序列的排列排序

时间:2019-06-11 20:45:45

标签: arrays algorithm combinations permutation ranking

我想通过长度给出的排列子集进行排名和取消排名。子集定义如下:

排列长度4的示例:

我们输入了位串长度3(始终为置换长度-1)

010

0表示2个连续元素在增加I

1表示2个连续元素在增加D

对于此位串,存在具有以下排列的子集:13241423231424133412

我要排列和取消排列的排列的位串定义子集?给定的位串有一种算法吗?

1 个答案:

答案 0 :(得分:1)

让我再说一遍我认为您的意思的问题。

您的字符串有点长n-1。如果其数字是增加/减少的模式,则说明一组适合该模式的排列。该集合可以按升序排列。

您希望能够解决两个问题。

  1. 给出适合模式的排列,说出排列顺序(即“排列”它)
  2. 给出一个数字,生成顺序中那个位置的排列(即“取消排序”)

理想情况下,您希望能够解决这些问题而不必生成适合模式的所有排列。

两者的关键是以下功能:

def count_matching (bitstring, start):
    ''' Returns how many permutations of 1..(len(bitstring) + 1)
    ''' match bitstring with starting value start
    # some implementation here.

可以很容易地递归计算。然而,天真的方法会产生所有排列。但是,如果我们在memoize上添加一个缓存层,那么我们将存储多项式数据并进行多项式调用以填充它。

这是为示例缓存后获得的数据:

{
    ('010', 1): 2,
    ('010', 2): 2,
    ('010', 3): 1,
    ('010', 4): 0,
    ('10', 1): 0,
    ('10', 2): 1,
    ('10', 3): 1,
    ('0', 1): 1,
    ('0', 2): 0,
    ('', 1): 1
}

现在,对于少量模式而言,这似乎是大量数据。但是对于长度为n的排列,条目的数量像O(n^2)一样增长,填充它的调用数量也像O(n^3)一样增长。 (任何老鹰眼的读者可能会发现如何及时O(n^2)来填充它。我将使用简单的版本。)


有了这个,我们可以对等级进行排序,并根据以下想法找出它必须是哪个排列。

假设我们要查找第4级排列。我们的数字起始列表是(1 2 3 4)。我们可以跳过以('010', 1)开头的0个排列,答案将是('010', 2) 2个中的第二个。

取第二个数字2,我们的部分置换为[2,我们得到数字(1 3 4)。我们正在寻找位串'10'的第二个。我们跳过以('10', 1)开头的0个排列,以('10', 2)开头的1个排列,而希望以('10', 3)开头的1个排列中的第一个。

取第三个数字4,我们的部分置换为[2, 4,我们有数字(1 3)。如前所述,我们希望使用('0', 1)中的第一个。

采用第一个数字1,我们的部分置换为[2, 4, 1,我们有数字(3)。选择不多。

因此,我们完成并获得[2, 4, 1, 3]。您可以验证的是第四名。

所以我们以[2, 4, 3, 1]结尾。


我们也可以采用其他方式。进行相同的排列,我们从[2, 4, 3, 1]开始,并希望其排名。

在此之前有多少个数字与第一位数不同?它使用了第二个可能的第一个数字。从('010', 1)的条目中我们知道有2。剩下的数字是1 3 4

之前有多少个与第二位数字不同?它使用第三个可能的第二个数字。从('10', 1)('10', 2)的条目中我们知道,前面还有1个。

我们现在剩下数字1 3。第三位没有任何数字。再说一次,最后没有。

前面有3个,必须具有4级​​。


就在那里。为了记住一个递归函数,您现在可以按等级查找排列,或者直接给定排列排列。