gpt4 book ai didi

两种递归方法的Java复杂度

转载 作者:搜寻专家 更新时间:2023-11-01 02:07:15 25 4
gpt4 key购买 nike

public static String rec1 (String s) {

int n = s.length()/2;
return n==0 ? s : rec1(s.substring(n)) + rec1(s.substring(0,n));
}


public static String rec2 (String s) {
return s.length()<=1 ? s : rec2(s.substring(1)) + s.charAt(0);
}

为什么rec2的复杂度大于rec1

我对每个迭代都进行了 10.000 次迭代,并使用 System.nanoTime() 测量了执行时间,结果如下:

rec1: Stringlength: 200  Avgtime: 19912ns Recursive calls: 399rec1: Stringlength: 400  Avgtime: 42294 ns Recursive calls: 799rec1: Stringlength: 800  Avgtime: 77674 ns Recursive calls: 1599rec1: Stringlength: 1600 Avgtime: 146305 ns Recursive calls: 3199rec2: Stringlength: 200  Avgtime: 26386 ns Recursive calls: 200rec2: Stringlength: 400  Avgtime: 100677 ns Recursive calls: 400rec2: Stringlength: 800  Avgtime: 394448 ns Recursive calls: 800rec2: Stringlength: 1600 Avgtime: 1505853 ns Recursive calls: 1600

所以当字符串长度为 1600 时,rec1 比 rec2 快 10 倍。我正在寻找一个简短的解释。

enter image description here

最佳答案

根据 Time complexity of Java's substring()String#substring 现在复制支持数组,O(n) 时间复杂度也是如此。

利用这个事实可以看出 rec1 具有时间复杂度 O(n log n)rec2 具有时间复杂度 O(n^2)

从初始 String s = "12345678" 开始。为简单起见,我将长度取为 2 的幂。

rec1 :

  1. s 分为 "1234""5678"
  2. 这些分为 "12" , "34" , "56" , "78"
  3. 这些分为 "1""2""3""4""5""6""7""8"

这里有 3 个步骤,因为 log(8) = 3 。每个 char 在每一步都被复制,所以复制的字符总数是 O(n log n) 。当 String 以相反的顺序重新组装时,上面的 Strings 现在使用连接连接在一起,使用以下步骤:

  1. 字符串被连接成 "21" , "43" , "65" , "87"
  2. 字符串连接成 "4321" , "8765"
  3. 连接字符串以生成 "87654321"

这又是一共O(n log n)复制的字符!

rec2 :

  1. s 分为 "1""2345678"
  2. "2345678" 分为 "2""345678"
  3. "345678" 分为 "3""45678"
  4. "45678" 分为 "4""5678"
  5. "5678" 分为 "5""678"
  6. "678" 分为 "6""78"
  7. "78" 分为 "7""8"

这是 8 + 7 + 6 + 5 + 4 + 3 + 2 = 35 复制字符的总数。如果你懂代数,这将是 (n * (n+1)) / 2 - 1 复制的一般字符,所以 O(n^2)

当这一切逆序拼装后,复制字符数又会是O(n^2)

关于两种递归方法的Java复杂度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29288677/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com