编程语言
首页 > 编程语言> > Java复杂性的两种递归方法

Java复杂性的两种递归方法

作者:互联网

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: 399

rec1: Stringlength: 400  Avgtime: 42294 ns Recursive calls: 799

rec1: Stringlength: 800  Avgtime: 77674 ns Recursive calls: 1599

rec1: Stringlength: 1600 Avgtime: 146305 ns Recursive calls: 3199

rec2: Stringlength: 200  Avgtime: 26386 ns Recursive calls: 200

rec2: Stringlength: 400  Avgtime: 100677 ns Recursive calls: 400

rec2: Stringlength: 800  Avgtime: 394448 ns Recursive calls: 800

rec2: Stringlength: 1600 Avgtime: 1505853 ns Recursive calls: 1600

所以在1600的强度下,rec1比rec2快10倍.我正在寻找一个简短的解释.

解决方法:

根据Time complexity of Java’s substring(),String#substring现在复制后备数组,因此具有O(n)时间复杂度.

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

从初始String s =“12345678”开始.为简单起见,我的长度是2的幂.

REC1:

> s分为“1234”和“5678”.
>这些分为“12”,“34”,“56”,“78”
>它们分为“1”,“2”,“3”,“4”,“5”,“6”,“7”,“8”

这里有3个步骤,因为log(8)= 3.每个步骤都复制每个字符,因此复制字符的总数为O(n log n).当以相反的顺序重新组装String时,现在使用串联将上述字符串连接在一起,使用以下步骤:

>字符串加入“21”,“43”,“65”,“87”
>字符串加入“4321”,“8765”
>字符串加入制作“87654321”.

这另外一共有O(n log n)复制的字符!

REC2:

> s分为“1”和“2345678”.
>“2345678”分为“2”和“345678”.
>“345678”分为“3”和“45678”.
>“45678”分为“4”和“5678”.
>“5678”分为“5”和“678”.
>“678”分为“6”和“78”.
>“78”分为“7”和“8”.

这是总共8 7 6 5 4 3 2 = 35个复制字符.如果你知道代数,一般来说这将是(n *(n 1))/ 2 – 1个复制字符,所以O(n ^ 2).

当这些都以相反的顺序组装时,复制字符数将再次为O(n ^ 2).

标签:java,complexity-theory,methods,recursion
来源: https://codeday.me/bug/20190528/1171088.html