简体   繁体   English

字符串排列算法的复杂性

[英]Complexity of a string permutation algorithm

Consider the following code to permute a string containing unique characters from McDowell: 考虑以下代码来置换包含McDowell的唯一字符的字符串:

This code is based on a recursion and adds to each result by placing a character to every single spot. 该代码基于递归,并通过在每个位置放置一个字符将其添加到每个结果中。 If the string contains n characters, then there are n+1 such places. 如果字符串包含n个字符,则存在n + 1个这样的位置。

Since for every string (there are n! possible strings of length n), you add n+1 characters, the complexity should be 1! 由于对于每个字符串(可能有n个长度为n的字符串),您要添加n + 1个字符,因此复杂度应为1! + 2! + 2! + ... + (n+1)! + ... +(n + 1)!

The author says that the complexity is O(n!). 作者说复杂度为O(n!)。 Is this the same as O(1!+...+(n+1)!)? 这和O(1!+ ... +(n + 1)!)一样吗? If so, why? 如果是这样,为什么?

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);
    String remainder = str.substring(1);
    ArrayList<String> words = getPerms(remainder);
    for (String word: words){
      for (int j = 0; j <= word.length(); j++){
        String s = insertCharAt(word, first, j);
        permutations.add(s);
      }
    }
    return permutations;
  }

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

Let's define F(n) as the length of the list returned by getPerms when you pass it a string of length n . 让我们将F(n)定义为getPerms返回的列表的长度,当您将长度为n的字符串传递给它时。

By inspection of the base case, we see that F(0) == 1 . 通过检查基本情况,我们看到F(0) == 1

In the recursive case, with a string of length n > 0 , getPerms calls itself recursively on a string of length n-1 . 在递归的情况下,如果字符串的长度为n > 0 ,则getPerms长度为n-1的字符串进行递归调用。 It gets back a list of length F(n-1) (that is the definition of F ) and stores the list in words . 它获取长度为F(n-1)的列表(即F的定义),并将该列表存储在words For each element of words , it adds n elements to permutations . 对于words每个元素,它将n元素添加到permutations Thus permutations will have n * F(n-1) elements when it is returned. 因此, permutations在返回时将具有n * F(n-1)元素。

Therefore, F(n) == n * (n-1) * (n-2) * ... * 1 == n! 因此, F(n) == n * (n-1) * (n-2) * ... * 1 == n! . The getPerms function returns a list of length n! getPerms函数返回长度为n!的列表n! given a string of length n . 给定一个长度为n的字符串。

Now, what is the complexity of getPerms ? 现在, getPerms复杂性getPerms I'll assume we're talking about time complexity. 我假设我们正在谈论时间复杂性。 Well, it performs ∑ i=0 n i! 好吧,它执行∑ i = 0 n i! list appends in total (n! for the outermost call, plus (n-1)! for the first recursive call, plus (n-2)! for the second recursive call, etc.). list总共追加(最外层调用n !,第一个递归调用加(n-1)!,第二个递归调用加(n-2)!,等等)。 So you could say the complexity is O(∑ n i!) list appends. 因此,您可以说复杂度是O(∑ n i!)列表的追加。

But list appends aren't the only computation here. 但是列表追加并不是这里唯一的计算方法。 We copy a lot of characters around when we join strings in Java. 当我们在Java中加入字符串时,我们会在周围复制很多字符。

Let's say G(n) is the number of character copies performed by a call to getPerms when you pass a string of length n . 假设G(n)是在传递长度为n的字符串时对getPerms的调用执行的字符副本n

By inspection of the base case, we see that G(0) == 0 . 通过检查基本情况,我们看到G(0) == 0

In the recursive case, getPerms calls itself on a string of length n-1 , which performs G(n-1) character copies and returns a list of F(n-1) strings, each of length n-1 . 在递归的情况下, getPerms在长度为n-1的字符串上调用自身,该字符串执行G(n-1)字符副本并返回F(n-1)字符串的列表,每个字符串的长度为n-1 Then getPerms copies each of those strings n times, inserting another character into each copy, so F(n-1) * n * n == n * n! 然后getPerms每个字符串复制n次,然后在每个副本中插入另一个字符,因此F(n-1) * n * n == n * n! characters copied directly in the getPerms call, in addition to the G(n-1) from the recursion. 除了递归中的G(n-1)外,还直接在getPerms调用中直接复制的字符。

Thus the number of characters copied by a call to getPerms is O(∑ i=0 n i * i!). 因此,通过调用getPerms复制的字符数为O(∑ i = 0 n i * i!)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM