我已经在Java中返回了以下代码,以生成可能的n位二进制表示形式。
public List<String> binaryRepresenation(int n){
List<String> list = new ArrayList<>();
if(n>0){
permuation(n, list, "");
}
return list;
}
private void permuation(int n, List<String> list, String str){
if(n==0){
list.add(str);
}else{
permuation(n-1, list, str+"0");
permuation(n-1, list, str+"1");
}
}
对于n = 3,它产生001 001 010 011 100 101 110 111组合。 总体而言,此功能会产生2 ^ n种可能的表示形式。
可以肯定地说时间复杂度是n * 2 ^ n
在2 ^ n次的情况下,针对基本情况调用该方法。为了达到每种基本情况,将调用置换方法最多n次。
那么总的上限时间复杂度是n * 2 ^ n吗?如果我错了,请纠正我。我基于此线程Time Complexity of Permutations of a String中讨论的字符串排列时间复杂度得出了这个结论。您的帮助将不胜感激。
答案 0 :(得分:3)
您的分析存在一个小问题。如您所见,对于每种基本情况,您必须调用该函数n次。但是,其中一些调用被其他基本情况共享。换句话说,您多次计算同一呼叫。
这意味着尽管复杂度绝对不能大于n * 2 ^ n
,但实际上可能更低。
要计算复杂度的更好界限,可以计算对permutation
函数的实际调用次数。一种实现方法是考虑str
变量的可能值。
str
将是长度小于或等于n
的二进制字符串。另外,每次对permutation
函数的调用都会收到一个唯一的值str
。这意味着该函数被调用的次数等于长度为<= n的二进制字符串的数量。
有多少个这样的字符串? 1 + 2 + 4 + ... + 2 ^ n = 2 ^ (n + 1) - 1
因此,permutation
的调用次数为O(2^n)
。
但是每个调用都包含操作str + "0"
和str + "1"
。这些操作需要O(n)
时间。因此,该操作的净时间复杂度为:O(n * 2^n)
,但出于与您最初想象的原因不同的原因。
答案 1 :(得分:1)
时间复杂度为O(2 n )。每个函数调用将两个新的函数调用压入堆栈,直到达到基本情况为止。可视化p $3.gsub(/20/,"").gsub(/../) { |b| b.hex.chr }
的树,如下所示:
n = 3
这是一个完美的二叉树,具有15个节点和8个叶子。访问了2 n + 1 个状态,但是我们可以删除常数并将其简化为O(2 n )。
字符串串联使复杂度增加了 ________""________
/ \
___0___ ___1___
/ \ / \
_00_ _01_ _10_ _11_
/ \ / \ / \ / \
000 001 010 011 100 101 110 111
,但是将n
或容器与恒定时间的push / pop或add / remove操作一起使用可以消除这种情况,这表明这只是一个实现特定于您发布的代码的细节,而不是一般算法的复杂性。