繁体   English   中英

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

[英]What is the complexity of finding permutation this way?

此方法:

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));
  }
}

查找字符串的所有排列。 permutation("","ABC");调用时permutation("","ABC"); 它打印:

ABC
ACB
BAC
BCA
CAB
CBA

现在的问题是:这种方法的复杂性是什么? O(n!)还是O(nlogn) 用递归树回答将非常有帮助! 谢谢,

都不:-)

令T(n,k)是调用置换的步数,其中k是str的长度。

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

对于1 <k <= n,我们有k个循环体执行,每个循环执行一些字符串连接(花费O(n))和递归调用花费T(n,k-1)。 因此,

T(n,k) = k (O(n) + T(n,k-1)). 

猜测这种重复发生的封闭形式的一种简单方法是写出一些术语:

T(n,k) = k * (n + (k-1) * (n + T(n,k-2)))

让我们将所有这n个术语分开:

       = 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

因此T(n,n)= O(nn!)

第一次尝试

由于您正在打印一个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", "")

如您所见,调用树的叶子具有以基本形式打印的prefix形式的必需排列。 由于这棵树的叶子数是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(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(nn!)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM