如何找到给定长度的k的排列?

时间:2010-02-28 05:34:55

标签: language-agnostic permutation

如何在给定长度内找到k的排列?

例如:

单词cat有3个字母:如何在单词cat中找到2的所有排列。 结果应为:acatcaac等...


这不是作业问题。 可以使用任何语言,但更优选:C / C ++或C#。 我知道如何为大小LENGTH创建递归,但不知道自定义大小的递归。

6 个答案:

答案 0 :(得分:3)

这是C#中的一个,即使重复的字符也可以使用。例如,对于长度为2的排列的“香蕉”,它给出了:

  

ba bn ab aa an nb na nn

基本思想是修复第一个字符,然后形成长度为k-1的所有排列,然后将字符添加到那些k-1长度排列。为了处理重复的字符,我们跟踪剩余的计数(即可用于子排列的计数)。

不是示例代码,但应该给你一个想法。 (如果你发现错误,请告诉我,我可以编辑)。

static List<string> Permutations(Dictionary<char, int> input, int length) {
    List<string> permutations = new List<string>();

    List<char> chars = new List<char>(input.Keys);

    // Base case.
    if (length == 0) {
        permutations.Add(string.Empty);
        return permutations;
    }

    foreach (char c in chars) {

        // There are instances of this character left to use.
        if (input[c] > 0) {

            // Use one instance up.
            input[c]--;

            // Find sub-permutations of length length -1.
            List<string> subpermutations = Permutations(input, length - 1);

            // Give back the instance.
            input[c]++;

            foreach (string s in subpermutations) {

                // Prepend the character to be the first character.
                permutations.Add(s.Insert(0,new string(c,1)));

            }
        }
    }

    return permutations;
}

以下是我的完整程序,使用它:

using System;
using System.Collections.Generic;

namespace StackOverflow {

    class Program {
        static void Main(string[] args) {
            List<string> p = Permutations("abracadabra", 3);
            foreach (string s in p) {
                Console.WriteLine(s);
            }
        }

        static List<string> Permutations(string s, int length) {
            Dictionary<char, int> input = new Dictionary<char, int>();
            foreach (char c in s) {
                if (input.ContainsKey(c)) {
                    input[c]++;
                } else {
                    input[c] = 1;
                }
            }
            return Permutations(input, length);
        }

        static List<string> Permutations(Dictionary<char, int> input, 
                                                          int length) {
            List<string> permutations = new List<string>();

            List<char> chars = new List<char>(input.Keys);
            if (length == 0) {
                permutations.Add(string.Empty);
                return permutations;
            }

            foreach (char c in chars) {
                if (input[c] > 0) {
                    input[c]--;
                    List<string> subpermutations = Permutations(input, 
                                                                length - 1);
                    input[c]++;

                    foreach (string s in subpermutations) {
                        permutations.Add(s.Insert(0,new string(c,1)));
                    }
                }
            }

            return permutations;
        }
    }
}

答案 1 :(得分:1)

递归解决方案有什么问题并传递一个额外的参数(深度),以便递归函数立即返回深度&gt; Ñ

答案 2 :(得分:1)

效率最高,但效果很好:

public class permutation
{
    public static List<string> getPermutations(int n, string word)
    {
        List<string> tmpPermutation = new List<string>();
        if (string.IsNullOrEmpty(word) || n <= 0)
        {
            tmpPermutation.Add("");
        }
        else
        {
            for (int i = 0; i < word.Length; i++)
            {
                string tmpWord = word.Remove(i, 1);
                foreach (var item in getPermutations(n - 1, tmpWord))
                {
                    tmpPermutation.Add(word[i] + item);
                }
            }
        }
        return tmpPermutation;
    }
}

答案 3 :(得分:1)

void Prem (char *str, int k, int length) {
    if (k == length-1){
         printf("%s\n",str);
         return;
    } else {
        for (int i = k ; i < length; ++i) {
            char t = str[k];
            str[k] = str[i];
            str[i] = t;
            Prem(str,k+1,length);
            t = str[k];
            str[k] = str[i];
            str[i] = t;
        }
    }
}

答案 4 :(得分:0)

如果我没弄错的话,这个问题也可以通过combinadics来解决,就像在http://en.wikipedia.org/wiki/Combinadic/上一样,那里也有参考实现。

我自己使用Java解决方案(http://docs.google.com/Doc?id=ddd8c4hm_5fkdr3b/)从一系列数字生成所有可能的三元组,这应该没有什么不同。

我没有足够的资金来解释它背后的数学,但据我所知,这是迭代所有可能的nCr(即你的猫例子中的3C2)选择的最简单的方法。

答案 5 :(得分:0)

首先找到数组的可能子集。你可以这样做 在Iterating over subsets of any size

中讨论的递归方式

其次使用STL算法计算每个子集的排列 next_permutation

我没有实现它,但我认为它应该有用。