Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.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 计算字符串的所有排列(破解编码访谈,第六章-示例12)_Java_String_Time Complexity_Big O_Permutation - Fatal编程技术网

Java 计算字符串的所有排列(破解编码访谈,第六章-示例12)

Java 计算字符串的所有排列(破解编码访谈,第六章-示例12),java,string,time-complexity,big-o,permutation,Java,String,Time Complexity,Big O,Permutation,在Gayle Laakman的书《破解编码面试》第六章(Big O),示例12中,问题指出,给定以下用于计算字符串排列的Java代码,需要计算代码的复杂性 public static void permutation(String str) { permutation(str, ""); } public static void permutation(String str, String prefix) { if (str.length() == 0) { S

在Gayle Laakman的书《破解编码面试》第六章(Big O),示例12中,问题指出,给定以下用于计算字符串排列的Java代码,需要计算代码的复杂性

public static void permutation(String str) {
    permutation(str, "");
}

public static void permutation(String str, String prefix) {
    if (str.length() == 0) {
        System.out.println(prefix);
    } else {
        for (int i = 0; i < str.length(); i++) {
            String rem = str.substring(0, i) + str.substring(i + 1);
            permutation(rem, prefix + str.charAt(i));
        }
    }
}
publicstaticvoid置换(stringstr){
排列(str,“”);
}
公共静态无效置换(字符串str、字符串前缀){
如果(str.length()==0){
System.out.println(前缀);
}否则{
对于(int i=0;i
这本书假设,既然有n!排列,如果我们认为每一个排列都是调用树中的一个叶子,其中每个叶子都被连接到一个长度为n的路径上,那么就不再有N*N了!树中的节点(即:调用次数不超过n*n!)

但节点的数量不应该是:

因为调用的数量等于节点的数量(请看视频中的图)

如果我们采用这种方法,节点数量将是1(对于第一层/树的根)+3(对于第二层)+3*2(对于第三层)+3*2*1(对于第四层/底层)

i、 e:节点数=3/3! + 3!/2! + 3!/1! + 3!/0! = 十六,

然而,根据上述方法,节点的数量将是3×3!=十八


我们是否应该将树中的共享节点计算为一个节点,因为它们表示一个函数调用?

根据您的视频,我们有3个字符的字符串(
ABC
),排列的数量是
6=3
6
恰好等于
1+2+3
。但是,如果我们有一个包含4个字符的字符串(
ABCD
),排列的数量应该是
4*3as
D
可以位于1到4之间的任何位置。使用
D
的每个位置,您可以生成
3其余部分的排列。如果您重新绘制树并计算排列的数量,您将看到差异

根据您的代码,我们有
n!=str.length()置换,但在置换的每次调用中,您还运行从0到n-1的循环。因此,您有
O(n*n!)


更新对已编辑问题的响应

首先,在编程中,我们经常使用
0->n-1
1->n
而不是
0->n

其次,在这种情况下,我们不计算节点的数量,因为如果您再次查看片段中的递归树,您将看到重复的节点。在这种情况下,排列应该是彼此唯一的叶子数


例如,如果您有一个包含4个字符的字符串,则叶数应为
4*3!=24
这将是排列的数量。但是,在您的代码片段中,在每个排列中也有一个
0->n-1=0->3
循环,因此您需要计算其中的循环。因此,在这种情况下,您的代码复杂度是
O(n*n!)=O(4*4!)

关于节点数量的说法是正确的。这个公式给出了精确的数字,但书中的方法计算了好几次

您的总和似乎也接近
e*n
用于大型
n
,因此可以简化为
O(n!)

从技术上讲,呼叫数不超过
n*n是正确的,因为这是一个有效的上限。根据使用方法的不同,这可能很好,也可能更容易证明

对于时间复杂度,我们需要乘以每个节点完成的平均功

首先,检查字符串连接。每次迭代都会创建
2
新字符串以传递给下一个节点。一个字符串的长度增加
1
,另一个字符串的长度减少
1
,但总长度始终为
n
,使得每次迭代的时间复杂度为
O(n)

每个级别的迭代次数各不相同,因此我们不能只乘以
n
。而是查看整个树的总迭代次数,并获得每个节点的平均值。使用
n=3

  • 第一级中的
    1
    节点迭代
    3次:
    1*3=3
  • 第二级中的
    3
    节点迭代
    2
    次:
    3*2=6
  • 第三级中的
    6
    节点迭代
    1
    时间:
    6*1=6
总迭代次数为:
3+6+6=15
。这与树中的节点数大致相同。因此,每个节点的平均迭代次数是恒定的


总的来说,我们有
O(n!)
迭代,每个迭代都
O(n)
工作,总时间复杂度为
O(n*n!)

为什么书中有
O(n^2*n!)
?只是一个错误?@AntonMalyshev这仍然是一个正确的上限,但不是一个严格的上限,因为他们高估了节点的数量。要么是因为错误,要么是为了简化证明。如果你想要的只是一个上限,你可以随意高估每个值,这取决于你希望答案的精确程度。谢谢@fgb,顺便说一句,我无法理解这本书这一部分中大多数“证据”的意思,太模糊了,我只是想知道它们是否相同。这基本上是一样的,我分享这一点是希望它能为那些数学技能需要热爱的人澄清一些事情(我的需要)。你的版本好多了!:)非常感谢。