[英]Complexity of a string permutation algorithm
考虑以下代码来置换包含McDowell的唯一字符的字符串:
该代码基于递归,并通过在每个位置放置一个字符将其添加到每个结果中。 如果字符串包含n个字符,则存在n + 1个这样的位置。
由于对于每个字符串(可能有n个长度为n的字符串),您要添加n + 1个字符,因此复杂度应为1! + 2! + ... +(n + 1)!
作者说复杂度为O(n!)。 这和O(1!+ ... +(n + 1)!)一样吗? 如果是这样,为什么?
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;
}
让我们将F(n)
定义为getPerms
返回的列表的长度,当您将长度为n
的字符串传递给它时。
通过检查基本情况,我们看到F(0) == 1
。
在递归的情况下,如果字符串的长度为n > 0
,则getPerms
长度为n-1
的字符串进行递归调用。 它获取长度为F(n-1)
的列表(即F
的定义),并将该列表存储在words
。 对于words
每个元素,它将n
元素添加到permutations
。 因此, permutations
在返回时将具有n * F(n-1)
元素。
因此, F(n) == n * (n-1) * (n-2) * ... * 1 == n!
。 getPerms
函数返回长度为n!
的列表n!
给定一个长度为n
的字符串。
现在, getPerms
的复杂性是getPerms
? 我假设我们正在谈论时间复杂性。 好吧,它执行∑ i = 0 n i! list总共追加(最外层调用n !,第一个递归调用加(n-1)!,第二个递归调用加(n-2)!,等等)。 因此,您可以说复杂度是O(∑ n i!)列表的追加。
但是列表追加并不是这里唯一的计算方法。 当我们在Java中加入字符串时,我们会在周围复制很多字符。
假设G(n)
是在传递长度为n
的字符串时对getPerms
的调用执行的字符副本n
。
通过检查基本情况,我们看到G(0) == 0
。
在递归的情况下, getPerms
在长度为n-1
的字符串上调用自身,该字符串执行G(n-1)
字符副本并返回F(n-1)
字符串的列表,每个字符串的长度为n-1
。 然后getPerms
每个字符串复制n
次,然后在每个副本中插入另一个字符,因此F(n-1) * n * n == n * n!
除了递归中的G(n-1)
外,还直接在getPerms
调用中直接复制的字符。
因此,通过调用getPerms
复制的字符数为O(∑ i = 0 n i * i!)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.