[英]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.