【问题标题】:Running time of permutation function置换函数的运行时间
【发布时间】:2015-08-01 05:55:52
【问题描述】:

我的书为计算一串唯一字符的所有排列的函数提供了以下代码(参见下面的代码),并说运行时间为 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;
}

来源:Cracking the Coding Interview

【问题讨论】:

  • @shekharsuman 这是书中提供的唯一代码。我同意它不完整。

标签: java performance algorithm recursion permutation


【解决方案1】:

根据我们的直觉,很明显没有现有算法可以生成 N 个项目的排列,其性能优于 O(n!),因为有 n!可能性。

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

Pn = nPn-1
P1 = 1

很容易看出Pn = 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)
    }
}

【讨论】:

    【解决方案2】:

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

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

    因此,继续我们将在每个步骤中处理N * (N - 1) * (N - 2) * ... 案例。

    因为N 元素的排列计数是N!,那么没有一种实现可以比N! 更快地排列长度为N 的数组。

    【讨论】:

    • 谢谢。您能否解释一下您的句子:“第一个字符可以是 N 个字符中的任何一个”?我认为这本书将“第一个字符”仅作为字符串开头的字符。因此,我认为第一个字符只能是一个可能的字符,而不是 N 个字符中的任何一个?
    • 查看带有字符串“123”的简短示例。该实现修复第一个字符'1',然后递归调用自身并接收字符串“23”和“32”。然后它将第一个字符插入到这些字符串的所有可能位置:第一个字符串为“123”、“213”、231”,第二个字符串为“132”、“312”、“321”。所以第一个字符在结果中不固定实际上。
    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2020-07-25
    • 1970-01-01
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多