给定数字集的排列

时间:2009-10-31 05:23:54

标签: c# .net permutation

有人可以解释一个好的算法,以有效的方式找到给定数字集的所有排列吗?

4 个答案:

答案 0 :(得分:8)

最简单的方法是递归方法,即可执行伪代码;

def permute(theseq):
  if len(theseq) <= 1:
    yield theseq
    return
  for i in range(len(theseq)):
    theseq[0], theseq[i] = theseq[i], theseq[0]
    for subperm in permute(theseq[1:]):
      yield theseq[:1] + subperm
    theseq[0], theseq[i] = theseq[i], theseq[0]

如果您不熟悉executable pseudocode,则表示[1:][:1]表示“切片”(分别是“除了第一个以外的所有”和“仅仅是第一个”) “),两个相同的任务执行”交换第0和第i项“和”将它们放回原位“的任务(即再次交换它们;-)。 yield表示“提供此结果,但在迭代时准备好继续”,而return表示“我们都已完成,再见!”。

在不同的性能轴上有一些更好的方法,但第一个里程碑是确保你完全熟悉基本的递归方法并彻底理解它 - 所以我现在停在这里。如果你完全理解这种方法,为什么它会很好,花花公子,如何以及为什么它在性能上看起来不是最佳,我会很高兴 扩展这个答案! - )

答案 1 :(得分:6)

答案 2 :(得分:3)

我的c#实现了Alex的伪代码:

    private int length;
    private List<List<string>> permutations;

    public List<List<string>> Generate(List<string> list)
    {
        length = list.Count;
        permutations = new List<List<string>>();

        foreach(List<string> subperms  in Recursive(list))
            permutations.Add(subperms);

        return permutations;
    }

    private List<List<string>> Recursive(List<string> list)
    {
        List<List<string>> subperms = new List<List<string>>();

        if (list.Count <= 1)
        {
            subperms.Add(list);
            return subperms;
        }

        for (int i = 0; i < list.Count; i++)
        {
            string temp = list[0];
            list[0] = list[i];
            list[i] = temp;

            List<string> tail = new List<string>(list);
            tail.RemoveAt(0);

            List<string> head = new List<string>();
            head.Add(list[0]);

            foreach (List<string> subperm in Recursive(tail))
            {
                List<string> headCopy = new List<string>(head);
                headCopy.AddRange(subperm);

                if (headCopy.Count == length)
                    permutations.Add(headCopy);
                else
                    subperms.Add(headCopy);
            }

            temp = list[0];
            list[0] = list[i];
            list[i] = temp;
        }

        return subperms;
    }

答案 3 :(得分:0)

你看过Knuth'计算机程序设计的艺术'吗?第3卷,排序和搜索涵盖了它,这是有道理的,因为排序会创建数据的特定排列。

警惕找到所有组合或排列的组合(和置换)算法。它们具有非常昂贵的Big-O表示法成本。