I'm stuck understanding how the author got the complexity of O(n^2 * n!)
of the following procedure which generates all permutation of a string.
void permutation(String str){
permutation(str,"");
}
void permutation(String str, String prefix){
if(str.length()==0){
System.out.println(prefix);
} else{
for(int i=0;i<str.length();i++){
String rem=str.substring(0,i)+str.substring(i+1);
permutation(rem,prefix+str.charAt(i));
}
}
}
A permutation, also called an “arrangement number” or “order,” is a rearrangement of the elements of an ordered list S into a one-to-one correspondence with S itself. A string of length n has n! permutation. Below are the permutations of string ABC. Here is a solution that is used as a basis in backtracking. C++.
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order. Example 1: Input: nums = [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
If diff = 0, then current index is the starting position of a substring permutation. Solve the problem first for a base case (e.g., n = 1) and then try to build up from there. Base Case and Build algorithms often lead to natural recursive algorithms. Example: Print all permutations of a string. For simplicity, assume all characters are unique.
You can return the answer in any order. Input: nums = [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]] All the integers of nums are unique.
The complexity of the method is O(n^2 *n!)
because of the else path cost:
First notice that each call to String rem=str.substring(0,i)+str.substring(i+1);
is O(n)
,
in the else
path we compute it n
times together with a call to permutation
which has complexity T(n-1)
.
Computing the complexity of this is equivalent to solving: T(n) = n[n+T(n-1)]
; n
times (the for loop) a work of (n+T(n-1))
Solving this recurrence is not that easy, If I'm not wrong it should boil down to solving:
But let's try to approximate.
Each permutation (base case) represent a node in the recursion tree. This tree has n!
leaf. Each leaf has a path to the root of length n
. So It is safe to assume there are not more than n*n!
nodes in the tree.
This is an upper bound on the number of calls to permutation
. Since each of this call costs n
then the overall upper bound on the complexity is O(n^2*n!)
Hope this helps.
I'm late to the party but nonetheless I will still post my answer.
This is how I explained it to myself.
Taking a simplified approach, lets ignore all the steps of the function: permutation(String str, String prefix)
except the recursive step.
Keeping above in mind, the time complexity of the function can be stated in terms of recurrence relation: T(N) = N*T(N-1)
, where N
is the length of the input string.
Upon expansion, T(N) = N*(N-1)*(N-2)*...3*2*1*T(0)
. --- (*)
Now, T(0) = O(N)
because in base case we are printing the prefix string, and printing a string of length N is an O(N) operation.
Expressing (*) above in closed form: N*N!
--- (1)
Now consider the following line of thepermutation
function:
String rem = str.substring(0, i) + str.substring(i + 1);
This is again O(N)
operation and this is done for each of the N!
recursive calls.
Therefore considering above and taking product with the expression (1) above, the total runtime complexity T(N)
turns out to be
N*N*N! = N^2*N!
A simple trick to solve this one is O(number of nodes * computation in each node).
computation in each node is O(n).
Number of nodes can be calculated by summing nodes at each level.
i.e. (n! / 1!) + (n! / 2!) + (n! / 3!) ... + (n! / n!)
which equals n! * (1/1! + 1/2! + ... + 1/n!)
The sum of this series (1/1! + 1/2! + ... + 1/n!) was considered as n (as an upper bound)
Which lead to make the number of nodes to be n * n!
So, O(number of nodes * computation in each node) is O( n * n! * n) which is O(n2 * n!)
But, if we do real math, (1/1! + 1/2! + ... + 1/n!) is 1.7182 ( where n is > 6 )
So, the number of nodes are 1.7182 * n!. The complexity must be O(1.7182 * n! * n) which is O(n * n!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With