【问题标题】:Generate all permutations of a list in lexicagraphical order按字典顺序生成列表的所有排列
【发布时间】:2013-04-22 16:31:33
【问题描述】:

我是个初学者。我正在尝试编写一个程序,给定列表中的元素数量(1-9)作为参数,然后按字典顺序输出列表的所有排列。在程序中,它将每个排列作为一个列表添加到一个更大的列表中,该列表按顺序包含所有排列。虽然程序通常没有按预期工作,但我遇到的一个主要问题是这个 while 循环 在第 10 行,我希望一旦将最终排列添加到列表中,列表就停止编译。例如,如果我的输入参数是 n = 4,那么最后一个排列/元素应该是 [4,3,2,1]。但是,当我运行这个程序时,该元素最后在列表中出现了 3 次。我不知道这是怎么回事,一旦添加了 while 循环就应该终止它。

def ourPermutations(n):
    x=list(range(1,n+1))
    permList = []
    permList+=[x]

    xcopy = x[:]
    finalPerm = xcopy[::-1]


    while x != finalPerm:
        istar = n-2
        while x[istar] > x[istar+1]:
            istar -= 1
        jstar = n-1
        while x[jstar] < x[istar]:
            jstar -= 1
        x[istar],x[jstar] = x[jstar],x[istar]
        if istar+1 == n-1:
            x = x[:]
        else:
            a = x[istar+1:]
            a = a[::-1]
            x = x[:istar+1] + a
        permList += [x]

    return permList

这是我的主要问题;但是,当我运行这个程序时,它仍然缺少元素。它不太好用,所以如果你发现某个地方有明显的问题,请随时告诉我那条特定的线路是导致我的问题的原因。如果有帮助,这是基于用 Mathematica 8 编写的相同(且正确)版本:

ourpermutations[n_] := (
    ourlist = {x=Range[1,n]};
    While[
        x != Reverse[Range[1,n]],
        istar = n-1;
        While[x[[istar]] > x[[istar+1, istar--];
        jstar = n; While[x[[jstar]] < x[[istar]], jstar--];
        x[[{istar, jstar}]] = x[[{jstar, istar}]];
        AppendTo[ourlist, x = Join[Take[x,istar], Reverse[Drop[x,istar]]]]
    ];
    ourlist
)

这就是我的 Python 代码应该做的事情;我还不能让它这样做。感谢您的时间和精力。

【问题讨论】:

  • 不是答案,但如果您不关心实施,itertools.permutations() 可能会有所帮助。
  • ourPermutations(3) 的输出应该是什么样子?
  • 谢谢,但是一位教授刚刚让我们尝试看看我们是否可以让它在其他语言中工作。输出应如下所示: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3 ,2,1]]

标签: python list while-loop permutation


【解决方案1】:

您似乎遇到了问题,因为您没有足够快地复制x,因此您有时会在将x 添加到permList 后对其进行修改。这可以通过在 while 循环的开头添加 x = x[:] 来解决:

def ourPermutations(n):
    x=list(range(1,n+1))
    permList = []
    permList+=[x]

    xcopy = x[:]
    finalPerm = xcopy[::-1]

    while x != finalPerm:
        x = x[:]
        istar = n-2
        while x[istar] > x[istar+1]:
            istar -= 1
        jstar = n-1
        while x[jstar] < x[istar]:
            jstar -= 1
        x[istar],x[jstar] = x[jstar],x[istar]
        if istar+1 == n-1:
            x = x[:]
        else:
            a = x[istar+1:]
            a = a[::-1]
            x = x[:istar+1] + a
        permList += [x]

    return permList

>>> ourPermutations(3)
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
>>> ourPermutations(4)
[[1, 2, 3, 4], [1, 2, 4, 3], [1, 3, 2, 4], [1, 3, 4, 2], [1, 4, 2, 3], [1, 4, 3, 2], [2, 1, 3, 4], [2, 1, 4, 3], [2, 3, 1, 4], [2, 3, 4, 1], [2, 4, 1, 3], [2, 4, 3, 1], [3, 1, 2, 4], [3, 1, 4, 2], [3, 2, 1, 4], [3, 2, 4, 1], [3, 4, 1, 2], [3, 4, 2, 1], [
4, 1, 2, 3], [4, 1, 3, 2], [4, 2, 1, 3], [4, 2, 3, 1], [4, 3, 1, 2], [4, 3, 2, 1]]

一个稍微“pythonic”的版本可能看起来像:

def our_permutations(n):
    x = list(range(1, n+1))
    perm_list = [x]
    final_perm = x[::-1]

    while x != final_perm:
        x = x[:]
        istar = n-2
        while x[istar] > x[istar+1]:
            istar -= 1
        jstar = n-1
        while x[jstar] < x[istar]:
            jstar -= 1
        x[istar],x[jstar] = x[jstar],x[istar]
        if istar+1 != n-1:
            a = x[istar+1:]
            a = a[::-1]
            x = x[:istar+1] + a
        perm_list += [x]

    return perm_list

对照itertools.permutation 检查这些函数表明它们产生了相同的答案,所以看起来你的算法是正确的,除了那个小错误。

【讨论】:

  • 是的,现在可以完美运行了。太感谢了!我仍然有点困惑,为什么只添加一行会改变它。为什么要更改 permList 中的 x?
  • @pomzer 没问题,很高兴为您提供帮助!问题是没有x=x[:] 行,x 仍然是对添加到permList 的列表的引用。同样的原因,如果你执行a = [1, 2]; b = a; b[0] = 3; 之类的操作,那么 a 和 b 都将是 [3, 2]。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
  • 1970-01-01
相关资源
最近更新 更多