任何人都可以向我解释这个算法的排列吗?

时间:2012-06-05 10:46:45

标签: algorithm

有人可以向我解释这种排列算法吗?我知道它有排列,但我无法弄清楚它为何起作用。

s = [1,2,3,4,5,6,7,8,9]  
def perm(s, i):
    if i == len(s):
        print s
    for j in range(i, len(s)):
        s[i], s[j] = s[j], s[i]
        perm(s, i + 1)
        s[i], s[j] = s[j], s[i]  //why it swaps back?      

2 个答案:

答案 0 :(得分:2)

此函数将数组s变为每个可能的排列,然后打印排列并在返回的路上反转变异。

在每个位置i,它会保留索引小于i的所有条目,尝试位置i中的所有后续值,并使用递归查找具有该集合的所有排列固定值和每个选择的位置i。在最高索引处,没有剩余的选择,但您找到了一个排列,因此它会打印出来。

我发现理解这种递归有助于在代码中添加额外的“调试打印”,如函数的开头和结尾,以及交换时的这种情况。

它当然不是最优雅的Python(一些调试打印应该被提取到函数中),但是运行这个版本的代码并添加了一些这些“调试打印”可能是有益的。

def perm(s, i):
    print '{padding}starting perm({list}, {index})'.format(list=s, index=i, padding=' '*i)
    if i == len(s):
        print s
    for j in range(i, len(s)):
        print '{padding}swapping s[{index1}]={entry1} and s[{index2}]={entry2}'.format(index1=i, entry1=s[i], index2=j, entry2=s[j], padding=' '*i)
        s[i], s[j] = s[j], s[i]
        perm(s, i + 1)
        print '{padding}swapping back s[{index1}]={entry1} and s[{index2}]={entry2}'.format(index1=i, entry1=s[i], index2=j, entry2=s[j], padding=' '*i)
        s[i], s[j] = s[j], s[i]
    print '{padding}returning from perm({list}, {index})'.format(list=s, index=i, padding=' '*i)

答案 1 :(得分:0)

它回转是因为它是python代码,这意味着s(列表)是可变的,因此在被调用函数中对它进行的更改会影响调用者中的数组。

如果它没有交换回来,那么在调用返回后,数组将处于“奇怪”状态(由之前的调用留下)。

另一种不应该突变的替代方案是:

s = [1,2,3,4,5,6,7,8,9]  
def perm(s, i):
    s = list(s) # copy before mutating
    if i == len(s):
        print s
    for j in range(i, len(s)):
        s[i], s[j] = s[j], s[i]
        perm(s, i + 1)

或者,或许更清楚:

    s = [1,2,3,4,5,6,7,8,9]
    def perm(s, i):
        if i == len(s):
            print s
        for j in range(i, len(s)):
            s[i], s[j] = s[j], s[i]
            perm(list(s), i + 1) # pass a copy

评论不确定为什么会被投票。用户同时对该问题发表了一些评论,但随后将其删除。我认为他们错了,我想删除评论意味着他们意识到了,但我不明白他们为什么不删除downvote(如果它们是他们的)。或者,如果这是错误的,请有人解释,以便我可以学习......