排列函数的运行时间

时间:2015-05-20 06:34:51

标签: java performance algorithm recursion permutation

我的书提供了以下代码,用于计算一串唯一字符的所有排列的函数(参见下面的代码),并说运行时间是O(n!),"因为有n !置换"

我不明白他们如何将运行时间计算为O(n!)。我认为他们的意思是" n"是原始字符串的长度。我认为运行时间应该是O((n + 1)XY),因为getPerms函数将被调用(n + 1)次,而X和Y可以表示外部和内部for循环的运行时间分别。有人可以向我解释为什么这是错的/本书的答案是对的吗?

感谢。

public static ArrayList<String> getPerms(String str)
{
    if (str == null)
        return null;

    ArrayList<String> permutations = new ArrayList<String>();

    if (str.length() == 0)
        permutations.add("");
        return permutations;

    char first = str.charAt(0); //first character of string
    String remainder = str.substring(1); //remove first character

    ArrayList<String> words = getPerms(remainder);
    for (String word: words)
    {
        for (i = 0; i <= word.length(); i++)
        {
            String s = insertCharAt(word, first, i);
            permutations.add(s)
        }
    }

    return permutations;

}

public static String insertCharAt(String word, char c, int j)
{
    String start = word.substring(0, i);
    String end = word.substring(i); 
    return start + c + end;
}

来源:破解编码面试

2 个答案:

答案 0 :(得分:2)

从我们的直觉中可以清楚地看出,没有现有的算法可以生成N个项目的排列,这些项目的性能优于O(n!),因为有n个!可能性。

您可以将递归代码缩减为递归等式,因为gePerm(n)其中n是长度为n的字符串将调用getPerm(n-1)。然后,我们使用它的所有值返回并放置一个循环N次的内部循环。所以我们有

  

P n = nP n-1
  P 1 = 1

很容易看出P n = n!通过伸缩方程式。

如果你很难想象我们如何提出这个等式,你也可以这样思考

ArrayList<String> words = getPerms(remainder);
for (String word: words)                          // P(n-1)
{
    for (i = 0; i <= word.length(); i++)          // nP(n-1)
    {
        String s = insertCharAt(word, first, i);
        permutations.add(s)
    }
}

答案 1 :(得分:1)

N元素的排列数为N * (N - 1) * (N - 2) * ... * 2 * 1,即N!

第一个字符可以是N个字符中的任何一个。下一个字符可以是剩余的N - 1个字符之一。现在我们已经有N * (N - 1)个可能的案例。

因此,继续我们每一步都会有N * (N - 1) * (N - 2) * ...个案例。

因为N元素的排列计数为N!,因此没有一个实现可以比N更快地置换长度为N的数组!