複雑さを評価するために、実行された再帰呼び出し let の数に注目しましょうC(n)
。
の呼び出しは、それぞれが独自のコストを追加する、n
正確に再帰的な呼び出しを意味します。2(n-1)
2(C(1)+C(2)+...C(n-1))
の呼び出しは、それぞれが独自のコストを追加する、n+1
正確に再帰的な呼び出しを意味します。2n
2(C(1)+C(2)+...C(n-1)+C(n))
の違いによりC(n+1)-C(n) = 2+2C(n)
、 と書くことができますC(n) = 2+3C(n-1)
。
C(1) = 0
C(2) = 2+2C(1) = 2+3C(0) = 2
C(3) = 4+2(C(1)+C(2)) = 2+3C(2) = 8
C(3) = 6+2(C(1)+C(2)+C(3)) = 2+3C(3) = 26
C(4) = 8+2(C(1)+C(2)+C(3)+C(4)) = 2+3C(4) = 80
...
C(n) = 2n-2+2(C(1)+C(2)+...C(n-1)) = 2+3C(n-1)
この再発を簡単に解決するには、次のことに注意してください。
C(n)+1 = 3(C(n-1)+1) = 9(C(n-2)+1) = ...3^(n-2)(C(2)+1) = 3^(n-1)
したがって、n>1
正確な式は
C(n) = 3^(n-1)-1
Catalan(1)
(一定時間)の呼び出し回数もC(n)
であり、加算または乗算の回数はC(n)/2
それぞれ です。
O(3^n)
ループ内のすべての項 (中央の項を除く) が 2 回計算されることに注意することで、複雑さを簡単に減らすことができO(2^n)
ますが、それでも受け入れ可能な実装にはなりません :)