web-dev-qa-db-ja.com

NリーフとN-1ノードから可能なすべてのバイナリツリーを列挙/生成する方法

私は 24 Game をansi Cに実装しようとしています。このゲームは次のようになります。

与えられた4つの数値のリストについては、これらの4つの数値を含むソリューションを見つけてください。加算(+)、減算(-)、乗算(*)および除算(/)を使用すると、24になります。各数値は、もちろん、数字の順番は変更される可能性があります。大括弧を使用してオペランドの順序を変更することができます(多くのソリューションではそうする必要があります)。

私はこの問題の上に構築して、[〜#〜] m [〜#〜]ゲームを発明したいと思いました。ここで、Mは任意の数にすることができ、任意の長さ[〜#〜] n [〜#〜]値のリスト。

私が知っていること:

  • 演算子は数式で複数回再利用できます。したがって、演算子を反復するとき、フラグを使用して、特定の演算子を特定の場所で使用する必要があるかどうかを確認できます。
  • 番号は1回しか使用できません。すべての異なる順序が使い果たされるまで配列を並べ替える方法を説明する 素晴らしいチュートリアル がそこにあります。

しかし、私がまだ問題を抱えているのは、演算子のさまざまな組み合わせをどのように決定するかです。

機能があるとしましょう

op(A、B)

この関数は非可換です。 op(A、B)!= op(B、A)。ここで、4つの値がある場合、これらの関数をどのように組み合わせる必要があるかを知りたいと思います。 カタロニア語の数字 のシーケンスは、オプションの数を示しています。 (4つの数値の場合、 5シーケンス があります)。これらは:

  1. op(A、op(B、op(C、D)))
  2. op(op(op(A、B)、C)、D)
  3. op(op(A、op(B、C)、D))
  4. op(A、op(op(B、C)、D))
  5. op(op(A、B)、op(C、D))

単純なbitVectorと再帰を使用して、最初の4つを見つけることができます。しかし、5つ目ではなく、2つのノードが同じ「レベル」を共有します。

これらすべての異なるオプションをテストする反復的な方法はありますか?

または、Ordousが適切に述べたように:

NリーフとN-1ノードからすべての可能なバイナリツリーを列挙/生成する方法

3
Qqwy

値の配列を取り、必要なすべてのツリーのリストを生成する再帰関数を定義します。

関数が値を1つだけ受け取ると、その値を唯一の要素として含むリストを返します。

関数が2つの値を受け取ると、これらの2つの値の演算を順番に単一の要素として含むリストを返します。

関数が3つ以上の値を受け取った場合、返すリストを保持し、配列のメンバー間のインデックスを反復処理する必要があります。配列のメンバー間の各インデックスについて、インデックスに基づいて配列を左の配列と右の配列に分割します。これらの配列を再帰し、それぞれのツリーのリストを生成します。次に、これが生成したリストの外積を取り、それをリストに追加して返します。

これが機能する方法は、3つ以上の値の配列の場合、複数の方法で分割できることです。配列を分割する方法ごとに、左側に可能なツリーが少なくとも1つあり、右側に可能なツリーが少なくとも1つあります。右側と左側の可能なツリーの各組み合わせは、可能なツリーです。

編集:ここにいくつかの擬似コードがあります(おおよそJava/python):

List<Tree> getOpTrees(List<Value> values):
    if (length(values) == 1):
        return new List(new IdentityTree(values[0]))
    if (length(values) == 2):
        return new List(new OpTree(values[0], values[1]))
   treeList = new List<Tree>()
   for (index from 1 to length(values)-1):
       leftList, rightList = values.split(index)
   for (leftTree : getOpTrees(leftList)):
   for (rightTree : getOpTrees(rightList)):
        treeList.add(new OpTree(leftTree, rightTree))
return treeList

実際には、n = 2の基本ケースも必要ないと思います。 n = 2の場合、index = 1のみになります。次に、左と右のリストを分割します。各リストには要素が1つだけ含まれます。それらはそれぞれ、要素のアイデンティティツリーを含む単一の要素リストを返します。次に、treeListに追加される唯一のものは、2つのIdentityTreeのOpTreeになります。

2
raptortech97