我想通过长度给出的排列子集进行排名和取消排名。子集定义如下:
排列长度4的示例:
我们输入了位串长度3(始终为置换长度-1)
010
0
表示2个连续元素在增加I
。
1
表示2个连续元素在增加D
。
对于此位串,存在具有以下排列的子集:1324
,1423
,2314
,2413
,3412
我要排列和取消排列的排列的位串定义子集?给定的位串有一种算法吗?
答案 0 :(得分:1)
让我再说一遍我认为您的意思的问题。
您的字符串有点长n-1
。如果其数字是增加/减少的模式,则说明一组适合该模式的排列。该集合可以按升序排列。
您希望能够解决两个问题。
理想情况下,您希望能够解决这些问题而不必生成适合模式的所有排列。
两者的关键是以下功能:
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级。
就在那里。为了记住一个递归函数,您现在可以按等级查找排列,或者直接给定排列排列。