📜  字符串所有排列的时间复杂度

📅  最后修改于: 2022-05-13 01:57:08.455000             🧑  作者: Mango

字符串所有排列的时间复杂度

打印字符串所有排列的时间复杂度。

1. void perm(String str){
2.    perm(str, "");
3.  }
4.
5. void perm(String str, String prefix){
6.     if(str.length() == 0){
7.         System.out.println(prefix);
8.     } else{
9.        for(int i = 0; i < str.length(); i++){
10.           String rem = str.substring(0, i) + 
                           str.substring(i + 1);
11.           perm(rem, prefix + str.charAt(i));
12.       }
13.    }
14. }

理解代码:

第 1-3 行:当调用函数perm“abc”作为字符串参数传递时,会进行对 perm(str, “”) 的内部调用。这意味着它以空前缀(第二个参数)开始为整个字符串(第一个参数)创建排列。

第 6-8 行:这是停止递归的基本情况。如果输入字符串中没有更多字符需要置换,则打印保存在变量前缀中的当前置换并返回。

第 9-12 行: for 循环每次从输入字符串中选择一个字符来更新前缀字符串。也就是说,循环使用更新的前缀和另一个字符串rem再次调用函数perm ,该字符串收集输入字符串的剩余字符。

借助下图了解这一点:

recusionInPermutation

分析时间复杂度:

1.函数perm 在其基本情况下被调用了多少次?
正如我们从上面解释的递归中可以理解的那样,对于长度为 3 的字符串,它正在打印 6 个排列,实际上是 3!。这是因为如果需要生成排列,则需要为每个槽选择字符。如果我们的字符串中有 3 个字符,则在第一个槽中,有 3 个选择,下一个槽有 2 个选择(对于前面的 3 个选择中的每一个,即乘法而不是加法)等等。这说明有n!排列在基本情况下打印,如图所示。

2.函数perm 在它的基本情况之前被调用了多少次?
考虑到第 9 到 12 行被命中n次。因此,不会有超过 (n * n!) 个函数调用。

3.每个函数调用需要多长时间?
由于字符串前缀的每个字符都需要打印,因此执行第 7 行将花费 O(n) 时间。由于字符串连接,第 10 行和第 11 行也将花费 O(n) 时间,因为 rem、prefix 和 str.charAt(i) 的总和将始终为 n。因此,每个函数调用对应于 O(n) 工作。

4. 总运行时间是多少?
调用 perm O(n * n!) 次(作为上限)并且每次调用需要 O(n) 时间,总运行时间不会超过O(n^2 * n!)

资料来源: Gayle Laakmann McDowell 对 Coding 的采访