简体   繁体   English

使用递归查找数组的排列

[英]Find the permutations of an array using recursion

I came up with the following function: 我想出了以下功能:

def permutations(elements, arr, index):
    if len(elements) == index:
        print arr
    for i in xrange(index, len(elements)):
        arr[index] = elements[i]
        permutations(elements, arr, index+1)

permutations([1,2,3], [0,0,0], 0)

However, it's printing: 但是,它正在打印:

[1, 2, 3]
[1, 3, 3]
[2, 2, 3]
[2, 3, 3]
[3, 2, 3]
[3, 3, 3]

what's wrong with my recursion? 我的递归怎么了?

Ok, I found this as a Java String recursive permutation algorithm that I translated to Python. 好的,我发现这是我翻译成Python的Java String递归置换算法。 I think it's the best solution: 我认为这是最好的解决方案:

def permutation(aux, ls):
    if len(ls) == 0: 
        print(aux)
    else:
        for i in range(len(ls)):
            permutation(aux + [ls[i]], ls[0:i] + ls[i+1:len(ls)])

permutation([], [1, 2, 3])

This is the output: 这是输出:

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

The main problem in your code is that on i-th position only possible values are from (i, n - 1) where is n length of list. 您代码中的主要问题是,在第i-th位置上,只有可能的值来自(i, n - 1) ,其中list的长度为n。 Thats why on last index in list you have all 3's. 这就是为什么在列表中的最后一个索引中您拥有全部3的原因。 So the solution would be to iterate on all "levels" ( i-th permutation call) from (0, n - 1) . 因此,解决方案是从(0, n - 1)遍历所有“级别”(第i-th置换调用(0, n - 1) But because you will iterate from (0, n - 1) on all "levels" you must introduce dictionary(used as hashset) where you will keep if some value ( j-th element) is already chosen on previous calls. 但是,因为您将在所有“级别”上从(0, n - 1)进行迭代,所以必须引入字典(用作哈希集),如果在先前的调用中已经选择了某个值(第j-th元素),则将保留该字典。 Easiest solution would be something like: 最简单的解决方案是:

def perm(elements):
    def inner(arr, index, visited):
        if len(elements) == index:
            print arr
        for i in xrange(0, len(elements)):
            if (i not in visited):
                visited[i] = 1; # mark so same index can not be used later
                arr[index] = elements[i]
                inner(arr, index + 1, visited);
                del visited[i] # free index
    inner([0] * len(elements), 0, {});         

perm([1,2,3])

As @Hooked already mentioned it would be best if you can use permutations function from itertools module . 正如@Hooked已经提到的,最好是可以使用itertools模块中的置换功能 Note that on Python 3, you can put arr and visited outside of function parameters with nonlocal . 需要注意的是关于Python 3,你可以把ARR与功能参数以外的受访nonlocal Also, here you are one more solution, without dictionary, but with additional list which will hold all possible values for i-th level (position) of permutation. 另外,这是您的另一种解决方案,没有字典,但是有附加列表,该列表将保存排列i-th级(位置)的所有可能值。 In this solution, however order of permutations is not preserved 在此解决方案中,但是不保留排列顺序

def perm(elements):
    def inner(arr, index, possible):
        if len(elements) == index:
            print arr
        lenForLevel = len(elements) - index;
        for i in xrange(0, lenForLevel):            
            arr[index] = possible[i]
            (possible[i], possible[lenForLevel - 1]) = (possible[lenForLevel - 1], possible[i])
            inner(arr, index + 1, possible);
            (possible[i], possible[lenForLevel - 1]) = (possible[lenForLevel - 1], possible[i])
    inner([0] * len(elements), 0, list(elements))

perm([1,2,3,4])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM