特定条件下置换的Python实现
在下列条件下,如何生成置换特定条件下置换的Python实现,python,algorithm,permutation,Python,Algorithm,Permutation,在下列条件下,如何生成置换 有两个整数,例如1和4 给定的两个整数将是排列的一部分,其中每个整数最多出现N次,每个排列的大小为K 因此,假设对于N=3和K=5,正确的结果应该是: {1,1,1,4,4},{1,1,4,1,4},{4,4,4,1,1},等等 以下是无效或不正确的结果示例: {1,1,1,1,4}->1出现4次(1应不超过3次) {1,4,4,4,1,1}->列表的大小是6(大小应该正好是5) 此外,每个排列应该是唯一的,这意味着没有重复 我希望我能得到这个问题的最佳解决方案或算法
提前感谢。:) 看看这是否适合你
>>> K=5
>>> N=3
>>> src=[['1']*n+['4']*(K-n) for n in xrange(K-N,N+1)]
>>> set(x for s in src for x in itertools.permutations(s))
set([('1', '4', '1', '4', '1'), ('4', '1', '4', '1', '1'), ('1', '1', '4', '4', '4'), ('1', '4', '4', '1', '1'), ('1', '4', '4', '4', '1'), ('4', '4', '4', '1', '1'), ('4', '1', '1', '4', '1'), ('4', '4', '1', '4', '1'), ('1', '4', '1', '1', '4'), ('4', '1', '4', '4', '1'), ('1', '1', '4', '4', '1'), ('1', '4', '4', '1', '4'), ('4', '1', '4', '1', '4'), ('4', '1', '1', '1', '4'), ('4', '4', '1', '1', '4'), ('1', '4', '1', '4', '4'), ('1', '1', '4', '1', '4'), ('4', '4', '1', '1', '1'), ('4', '1', '1', '4', '4'), ('1', '1', '1', '4', '4')])
注**
首先使用“1”和“4”创建所有可能的组合。请注意,限制了特定整数的最大N个实例,因此在一组K个数中,如果x有i个实例,那么对于两个数(x,y),y有(K-i)个实例。在这种情况下,i和x都应该在[K-N,N]范围内
现在,下一步是使用生成器理解来创建上述集合的所有可能实例的所有可能迭代。我使用集合理解来删除任何副本,并且使用生成器来不存储中间副本结果 这是思考这个问题的一种方式,尽管我想知道一个更优雅的解决方案: 假设N=3,K=5,如上所述。 我将使用
a
和b
来代替你的'1'和'4',否则我会把自己弄糊涂:P
由于每个符号(a
或b
)最多只允许出现3次,这意味着我们希望获得以下所有排列:
- 2
s在一个5a
s的字符串中b
- 3
s在一个5a
s的字符串中b
{a,a,b,b,b}
和{a,a,a,b,b}
的所有排列
一般来说,您只需要找到{m lots a和(K-m)lots b}
的排列,其中m
位于{K-N,K-N+1,K-N+2,…N}
一种方法是:
m=K-N
b
创建一个列表,称之为x
x
(即0,1,2,…,K-1
),并将长度m
的所有子集放入该列表。这些将是我们放置a
s的位置m=K-N,K-N+1,N
itertools
,尤其是itertools.compositions
因此:
然后:
另一种方法是使用
itertools.permutations
查找{m lots of symbol1,和(K-m)lots of symbol2}
的所有置换。除了在那里得到重复(因为Python基于元素的唯一位置进行排列,而不是元素的唯一值)。然后你需要过滤掉它们,一旦K
和N
变大,它们就会变得昂贵。这就是我选择上述方法的原因,因为它不存在重复的问题。对于较小的K值,我将从0计数到2^K-1,跳过二进制表示形式大于n0或大于n1的值,然后将0位转换为“1”,将1位转换为“4”
对于较大的K值,可以使用回溯搜索-
PseudoCode (int N, int K, int num1s, int num4s, String sofar)
if (num1s > K)
return
if (num4s > K)
return
length(sofar) == N
print sofar
return
PseudoCode (N, K, num1s + 1, num4s, sofar + "1")
PseudoCode (N, K, num1s, num4s + 1, sofar + "4")
从这里开始(如阿比吉特的回答)
…然后,您可以为每个列表选择。另外,如果N
N=max(N,K-N)
来处理这个问题。呃,忽略这个答案,@Abhijit's更好:p。我不知道set
。谢谢你的解释。无论如何,使用你的代码,我尝试了类似len(notQuitePermutations(50100,1,5))的东西,我得到了一个“MemoryError”,所以我想它对于较大的值是无效的。我想要的是一个有效的算法。不,不要忽略这个,它对更大的N和K更有效。嗨,我试过这个,我得到一个错误,说“s”没有定义。同样根据您的输出,4始终最多只出现2次,这样的排列->(4,4,4,1,1)也应该考虑。所以基本上你的输出是不完整的。。谢谢你的努力。@Manie,有个小问题我解决了。您现在应该得到类似于您提到的排列。顺便问一下,你使用的是什么版本的python?你能提供完整的堆栈跟踪吗?我看不出这有什么理由不起作用。只要尝试一下,如果失败了,请提供堆栈跟踪。嗨,我得到了它,我所做的是将集合(在itertools.permutations(s)for s in src)重新排列为set(x for s in src for x in itertools.permutations(s)),以获得正确的结果。是的,这是我的问题。您可以检查上面的修复。理解src时也有一个问题,现在已经解决了。@Manie,顺便说一句,如果这个解决方案有效,您可能希望选择这个答案作为接受的答案
>>> notQuitePermutations(3,5,1,4)
[[1, 1, 4, 4, 4], [1, 4, 1, 4, 4], [1, 4, 4, 1, 4],....
PseudoCode (int N, int K, int num1s, int num4s, String sofar)
if (num1s > K)
return
if (num4s > K)
return
length(sofar) == N
print sofar
return
PseudoCode (N, K, num1s + 1, num4s, sofar + "1")
PseudoCode (N, K, num1s, num4s + 1, sofar + "4")
>>> K=5
>>> N=3
>>> [['1']*n+['4']*(K-n) for n in xrange(K-N,N+1)]
[['1', '1', '4', '4', '4'], ['1', '1', '1', '4', '4']]