如果满足以下条件,我如何生成排列?
让我们说 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)
此外,每个排列应该是唯一的,这意味着没有重复。
我希望我能为这个问题找到最佳解决方案或算法。
提前致谢。 :)
答案 0 :(得分:4)
看看这是否适合你
>>> 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个数中,如果有i个实例,那么对于两个数字(x,y)存在y的(K-i)个实例。在这种情况下,i和x都应该在[K-N,N]范围内。
现在,下一步是使用生成器理解来创建上述集合的所有可能实例的所有可能迭代。我使用set comprehension删除任何重复项,并使用生成器不存储中间重复结果。
答案 1 :(得分:2)
从这里开始(如Abhijit的回答)......
>>> 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']]
...然后您可以为每个列表Generate permutations of list with repeated elements。此外,如果N <1,则处理该情况。 K-N,可能是设置N=max(N,K-N)
答案 2 :(得分:1)
这是考虑它的一种方式,虽然我想知道更优雅的解决方案:
假设N = 3且K = 5,如上所述。
而不是你的'1'和'4'我会使用a
和b
,否则我会迷惑自己:P
由于每个符号(a
或b
)最多只能出现3次,这意味着我们希望获得以下所有排列:
a
s,串成5 b
s a
s,串成5 b
s 因此,我们只需找到{a,a,b,b,b}
和{a,a,a,b,b}
的所有排列。
对此进行概括,您只需找到{m lots of a, and (K-m) lots of 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
。要执行第4步,我们使用模块itertools
,尤其是itertools.combinations
。
所以:
import itertools
def notQuitePermutations(N,K,symbol1,symbol2):
permutations = []
base_perm = [symbol2]*K # step 3
for m in range(K-N,N+1): # +1 so we *include* N
# step 4: find m places to put symbol1 in.
idxs = itertools.combinations(range(K),m)
for idx in idxs:
perm = base_perm[:] # make a copy of base_perm
for i in idx:
perm[i] = symbol1 # put symbol1 in.
# add this permutation to the list
permutations += [perm]
return permutations
然后:
>>> notQuitePermutations(3,5,1,4)
[[1, 1, 4, 4, 4], [1, 4, 1, 4, 4], [1, 4, 4, 1, 4],....
另一种方法是使用{m lots of symbol1, and (K-m) lots of symbol2}
查找itertools.permutations
的所有排列。除了你在那里得到重复之外(因为Python根据元素的唯一位置进行排列,而不是元素的唯一值)。然后,您需要在之后对其进行过滤,一旦K
和N
变大,这可能会变得昂贵。这就是我选择上述方法的原因,因为它没有重复的问题。
答案 3 :(得分:0)
对于小的KI值将从0到2 ^ K-1计数,跳过二进制表示具有大于N 0或大于N 1的值,然后将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")