Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用这种方法寻找排列的复杂性是什么?_Java_Algorithm_Asymptotic Complexity - Fatal编程技术网

Java 用这种方法寻找排列的复杂性是什么?

Java 用这种方法寻找排列的复杂性是什么?,java,algorithm,asymptotic-complexity,Java,Algorithm,Asymptotic Complexity,此方法: private static void permutation(String prefix, String str) { int n = str.length(); if(n==0) System.out.println(prefix); else { for(int i=0;i<n;i++) permutation(prefix+str.charAt(i),str.substring(0,i)+str.substring(i+1,n)

此方法:

private static void permutation(String prefix, String str)
{
  int n = str.length();
  if(n==0)
    System.out.println(prefix);
  else
  {
    for(int i=0;i<n;i++)
      permutation(prefix+str.charAt(i),str.substring(0,i)+str.substring(i+1,n));
  }
}
现在的问题是:这种方法的复杂性是什么?是
O(n!)
还是
O(nlogn)
。使用递归树的答案将非常有用!谢谢,

第一次尝试 由于您正在打印
n
-字符串的每个排列,因此存在这样的
n字符串,时间复杂度显示为
O(n!)

重复性可以用图形显示(不完整,但你应该知道),如下所示:

             -------------- p("", "ABC")------------
            /                 |                 \
      p("A", "BC")        p("B", "AC")        p("C", "AB")
       |         |  
p("AB", "C")    p("AC", "B")
       |             |
p("ABC", "")     p("ACB", "")
如您所见,调用树的叶子具有所需的排列形式,即
前缀
,您可以在基本情况下打印它。因为这棵树的叶子数是
n,复杂性出现
O(n!)

为什么它不是(低至)
O(nlogn)
的一个直观推理是,其他
O(nlogn)
的复发看起来不是这样的。例如,在合并排序的情况下,将问题大小减半,并在每个步骤中执行线性合并操作。由于存在
log(n)
步骤,因此可以使用
O(nlog(n))
作为循环的解决方案。然而,在这个问题中,由于您需要做更多的工作,所以时间复杂度更高

评论后更新 上述第一次尝试中的分析并不完全正确。这里还有很多事情要做。调用树确实有
n离开。但是为了获得这些叶子,我们必须在每个表示递归调用的非叶子节点上做更多的工作。对于具有
n
字符的字符串
str
,第一级中的节点数显然是
n
。在进行下一个递归调用之前,还会进行字符串连接。这使得它更加耗时。每个
n
调用最后都会附加至少
n
个字符

在第二级,每个
n
节点产生
(n-1)
节点,总共产生
n(n-1)
。同样,有尽可能多的字符串连接

这个过程一直持续到递归达到最低点,给出
n在调用树中留下。调用树中的节点总数为

= n + n(n-1) + n(n-1)(n-2) + ... + n(n-1)(n-2)...1
= n(n-1)(n-2)...1 + n(n-1)(n-2)...2 + n(n-1)(n-2)...3 + ... + n(n-1) + n
= n! + (n!/2) + (n!/(2.3)) + ... + (n!/(1.2.3...(n-1)) --- these are n terms
= n! (1 + 1/2 + 1/2.3 + 1/2.3.4 + ...)
= n! (1.71828...)
= O(n!)
在每一个调用中,都至少添加了
n
字符(正如Paul指出的,正在打印一行新行),总工作量是
O(n.n!)
两者都不是:-)

设T(n,k)为置换调用的步数,其中k为
str
的长度

显然,T(n,0)=O(n)


对于1(n+1),但是
n.nn=length(“str”)
,则输出code>(18=3.3!)个字符。但是我同意,调用
permutation
的次数多于
O(n!)
。每行有(n+1)个字符:n个数字和一个回车符。所以(n+1)!总计。我认为括号内术语的正确界限是1。有一个大小为k的循环,而不是n。递归关系解释了这一点,因为k(n+…)=kn+k…至于界:虽然x= n + n(n-1) + n(n-1)(n-2) + ... + n(n-1)(n-2)...1 = n(n-1)(n-2)...1 + n(n-1)(n-2)...2 + n(n-1)(n-2)...3 + ... + n(n-1) + n = n! + (n!/2) + (n!/(2.3)) + ... + (n!/(1.2.3...(n-1)) --- these are n terms = n! (1 + 1/2 + 1/2.3 + 1/2.3.4 + ...) = n! (1.71828...) = O(n!)
T(n,k) = k (O(n) + T(n,k-1)). 
T(n,k) = k * (n + (k-1) * (n + T(n,k-2)))
       = kn + k(k-1)n + k(k-1)T(n,k-2)
       = kn + k(k-1)n + k(k-1)(k-2)n + k(k-1)(k-2)T(n,k-3)
T(n,k) = kn + k(k-1)n + k(k-1)(k-2)n + ... + k!n
       = n (k + k(k-1) + k(k-1)(k-2) + ... + k!)
T(n,n) = n (n + n(n-1) + n(n-1)(n-2) + ... + n!)
       = nn! (1/(n-1)! + 1/(n-2)! + 1/(n-3)! + ... + 1)
             \-----------------   --------------------/
                               \ /
                            1 < x < 2