giulio
giulio

Reputation: 659

Complexity of a string permutation algorithm

Consider the following code to permute a string containing unique characters from 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.

Since for every string (there are n! possible strings of length n), you add n+1 characters, the complexity should be 1! + 2! + ... + (n+1)!

The author says that the complexity is O(n!). Is this the same as 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;
  }

Upvotes: 0

Views: 657

Answers (1)

rob mayoff
rob mayoff

Reputation: 385710

Let's define F(n) as the length of the list returned by getPerms when you pass it a string of length n.

By inspection of the base case, we see that 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. It gets back a list of length F(n-1) (that is the definition of F) and stores the list in words. For each element of words, it adds n elements to permutations. Thus permutations will have n * F(n-1) elements when it is returned.

Therefore, F(n) == n * (n-1) * (n-2) * ... * 1 == n!. The getPerms function returns a list of length n! given a string of length n.

Now, what is the complexity of getPerms? I'll assume we're talking about time complexity. Well, it performs ∑i=0ni! 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.). So you could say the complexity is O(∑ni!) list appends.

But list appends aren't the only computation here. We copy a lot of characters around when we join strings in 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.

By inspection of the base case, we see that 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. Then getPerms copies each of those strings n times, inserting another character into each copy, so F(n-1) * n * n == n * n! characters copied directly in the getPerms call, in addition to the G(n-1) from the recursion.

Thus the number of characters copied by a call to getPerms is O(∑i=0ni * i!).

Upvotes: 1

Related Questions