二分木
二分木は、3つのタイプのノードを持つツリーです。
- 子を持たないターミナルノード
- それぞれが1つの子を持つ単項ノード
- それぞれ2つの子を持つバイナリノード
BNF(Backus–Naur形式)で与えられる次の文法でそれらを表現できます。
<e> ::=
<terminal>
| <unary>
| <binary>
<terminal> ::=
"0"
<unary> ::=
"(1" <e> ")"
<binary> ::=
"(2" <e> " " <e> ")"
この文法では、ノードは事前順序で指定され、各ノードは、子の数である数字で表されます。
モッツキン数
Motzkin番号(OEIS)(Wikipedia)には多くの解釈がありますが、1つの解釈は、n
th Motzkin番号はn
ノードを持つ別個の二分木の数であるということです。Motzkin番号の表が始まります
N Motzkin number M(N)
1 1
2 1
3 2
4 4
5 9
6 21
7 51
8 127
...
たとえばM(5)
、9であり、5つのノードを持つ9つの異なる二分木は
1 (1 (1 (1 (1 0))))
2 (1 (1 (2 0 0)))
3 (1 (2 0 (1 0)))
4 (1 (2 (1 0) 0))
5 (2 0 (1 (1 0)))
6 (2 0 (2 0 0))
7 (2 (1 0) (1 0))
8 (2 (1 (1 0)) 0)
9 (2 (2 0 0) 0)
仕事
n
入力として単一の正の整数を取り、n
ノードを持つすべての異なるバイナリツリーを出力します。
n
読みやすくするために括弧を含む1〜5の例
0
(1 0)
(1 (1 0))
(2 0 0)
(1 (1 (1 0)))
(1 (2 0 0))
(2 0 (1 0))
(2 (1 0) 0)
(1 (1 (1 (1 0))))
(1 (1 (2 0 0)))
(1 (2 0 (1 0)))
(1 (2 (1 0) 0))
(2 0 (1 (1 0)))
(2 0 (2 0 0))
(2 (1 0) (1 0))
(2 (1 (1 0)) 0)
(2 (2 0 0) 0)
入力
入力は1つの正の整数になります。
出力
出力は、その数のノードを持つ明確なバイナリツリーのわかりやすい表現である必要があります。上記のBNF文法で指定された正確な文字列を使用することは必須ではありません。使用する構文がツリーの明確な表現を提供することで十分です。例えば、あなたが使用できる[]
代わりに()
、余分な括弧のレベル[[]]
の代わりに[]
など、外側のカッコ存在しているか欠落している、余分なカンマや無カンマ、余分なスペース、括弧、または全くカッコを、
これらはすべて同等です。
(1 (2 (1 0) 0))
[1 [2 [1 0] 0]]
1 2 1 0 0
12100
(1 [2 (1 0) 0])
.:.--
*%*55
(- (+ (- 1) 1))
-+-11
コメントの@xnorが意図したバリエーション。これを理解できる形式に変換する方法があるので、それは受け入れられます。
[[[]][]] is (2 (1 0) 0)
これを容易に理解するようにするには、いくつかのを変換[]
する()
ので、好き
[([])()]
今から始めたら
[]
次に、取得する2つの式を必要とするバイナリを挿入します
[()()] which is 2
そして、最初の()のために、あなたが得る1つの式を必要とする単項式を挿入します
[([])()] which is 21
しかし、以来、[]
または()
それ以上の表現を必要としない0を表すことができていないインナーブラケットを使用すると、としてそれを解釈することができます
2100
回答は理論的には無限のメモリで機能するはずですが、実装依存の有限入力では明らかにメモリが不足することに注意してください。
出力のバリエーション
BNF xnor Christian Ben
b(t, b(t, t)) [{}{{}{}}] (0(00)) (1, -1, 1, -1)
b(t, u(u(t))) [{}{(())}] (0((0))) (1, -1, 0, 0)
b(u(t), u(t)) [{()}{()}] ((0)(0)) (1, 0, -1, 0)
b(b(t, t), t) [{{}{}}{}] ((00)0) (1, 1, -1, -1)
b(u(u(t)), t) [{(())}{}] (((0))0) (1, 0, 0, -1)
u(b(t, u(t))) [({}{()})] ((0(0))) (0, 1, -1, 0)
u(b(u(t), t)) [({()}{})] (((0)0)) (0, 1, 0, -1)
u(u(b(t, t))) [(({}{}))] (((00))) (0, 0, 1, -1)
u(u(u(u(t)))) [(((())))] ((((0)))) (0, 0, 0, 0)
重複したツリーをチェックできる場所
重複をチェックする1つの場所はM(5)です。
この1つのツリーは、M(4)ツリーからM(5)に対して2回生成されました
(2 (1 0) (1 0))
最初に単項ブランチを追加する
(2 (1 0) 0)
次に、単項ブランチを追加する
(2 0 (1 0))
BNFを理解する
BNFは単純なルールで構成されています。
<symbol> ::= expression
ここで、左側はで囲まれたシンボル名<>
です。
右側は、シンボルを構築するための式です。いくつかのルールは、構築に他のルールを使用します。例えば
<e> ::= <terminal>
e
することができます terminal
また、一部のルールには、シンボルの構築に使用される文字があります。
<terminal> ::= "0"
terminal
文字ゼロです。
いくつかのルールには、複数の構築方法があります。例えば
<e> ::=
<terminal>
| <unary>
| <binary>
e
することができ<terminal>
たり<unary>
または<binary>
。
そして、いくつかのルールはパーツのシーケンスです、例えば
<unary> ::= "(1" <e> ")"
Aはunary
文字である(1
ために構築することができるものが続くe
続きます)
。
常に開始ルールから開始し<e>
ます。これはこのためです。
いくつかの簡単な例:
最も単純なシーケンスはjust 0
です。したがって、開始ルールから始めて、<e>
3つの選択肢があることを確認します。
<terminal>
| <unary>
| <binary>
だから最初のものを取る<terminal>
。現在、端末には選択肢がなく、です0
。そのため、ルール内でを置き換える<terminal>
と完了です。0
<e>
その後、次の1です(1 0)
。で始まる<e>
ルール<unary>
を使用する
"(1" <e> ")"
今、これが必要な<e>
ので、戻って<e>
3つのうちの1つを選択し、今回は選択<terminal>
します0
。交換0
に(1 <e> )
与え(1 0)
、これはに置き換えられ<unary>
そう<e>
です(1 0)
。