Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで2つの二分木の葉の並び(シーケンス)が同じかどうかを確認する方法

はじめに

2つの二分木が与えられたとき、それぞれの木を左から右へたどったときの葉ノードの並び(シーケンス)が一致しているかどうかを判定する問題を考えてみましょう。

例えば、次のような2つの木が入力として与えられた場合を想定します。

Pythonで2つの二分木の葉の並び(シーケンス)が同じかどうかを確認する方法

この場合、どちらの木も葉の並びは [2, 6] となるため、出力は True になります。

解決のアプローチ

この問題を解くためには、以下の手順に従います。

  • 結果を格納するための新しいリスト c を用意します。
  • inorder() 関数を定義します。この関数はルートノードとリスト c を引数に取ります。
  • cnull の場合は、新しい空のリストを作成します。
  • ルートノードが null でない場合、以下の処理を行います。
    • まず左部分木に対して再帰的に inorder() を呼び出します。
    • 現在のノードが左の子も右の子も持たない(=葉ノードである)場合、その値をリスト c の末尾に追加します。
    • 続いて右部分木に対して再帰的に inorder() を呼び出します。
  • 最後にリスト c を返します。
  • メイン処理では、inorder(root0)inorder(root1) の結果を比較し、一致していれば True、そうでなければ False を返します。

それでは、実際のコード実装を見てみましょう。

サンプルコード

class TreeNode:
   def __init__(self, data, left = None, right = None):
      self.val = data
      self.left = left
      self.right = right

class Solution:
   c = []

   def inorder(self, root, c=None):
      if c is None:
         c = []
      if root:
         self.inorder(root.left, c)
         if not root.left and not root.right:
            c.append(root.val)
         self.inorder(root.right, c)
      return c

   def solve(self, root0, root1):
      if self.inorder(root0) == self.inorder(root1):
         return True
      else:
         return False

ob = Solution()
root1 = TreeNode(1)
root1.right = TreeNode(3)
root1.right.left = TreeNode(2)
root1.right.right = TreeNode(6)

root2 = TreeNode(1)
root2.left = TreeNode(3)
root2.right = TreeNode(6)
root2.left.left = TreeNode(2)
print(ob.solve(root1, root2))

入力

root1 = TreeNode(1)
root1.right = TreeNode(3)
root1.right.left = TreeNode(2)
root1.right.right = TreeNode(6)

root2 = TreeNode(1)
root2.left = TreeNode(3)
root2.right = TreeNode(6)
root2.left.left = TreeNode(2)

出力

True

コードのポイント

  • 中順走査(In-order Traversal)の活用: 二分木を中順に走査することで、葉ノードを必ず左から右の順序で訪問できます。これにより、葉の並びを自然な順序で取得できます。
  • 葉ノードの判定: 「左の子と右の子がどちらも存在しない」という条件で葉ノードを識別しています。
  • 可変デフォルト引数への対策: Pythonではリストなどのミュータブルなオブジェクトをデフォルト引数にすると予期しない動作を起こすため、c=None として関数内で新規リストを作成しています。

まとめ

このアルゴリズムの計算量は、木のノード数を n とすると時間計算量 O(n)、再帰呼び出しによる空間計算量 O(n) となります。2つの木の構造が異なっていても、葉ノードの値の並びさえ一致していれば True が返される点がポイントです。同様の手法は、木の比較やパターンマッチングの問題にも応用できます。

  1. Pythonで二分木の隣接ノードが同じ色にならないように着色できるか判定するプログラム

    各ノードの値がそのノードの色を表す二分木を考えます。木に含まれる色は最大で2色です。ここで、ノード同士の色を何度でも入れ替えられるとき、辺でつながれた隣接ノード同士が同じ色にならないような配置が可能かどうかを判定します。 たとえば、入力が次のような木だったとします。 この場合の出力は True です。色を入れ替えることで、次のようにすべての隣接ノードが異なる色になる状態を作れるからです。 解法のアプローチ この問題は、次の手順で解くことができます。 colors := 空のマップ(各色を持つノードの個数を記録) prop := 空のマップ(フラグごとのノード数を記録) dfs() 関数

  2. Pythonで与えられたグラフが2部グラフかどうかを判定するプログラム

    2部グラフとは無向グラフが与えられたとき、そのグラフが2部グラフ(バイパータイトグラフ)であるかどうかを判定する方法を解説します。2部グラフとは、グラフのすべての頂点を2つの集合 A と B に分割でき、グラフ内のすべての辺 {u, v} が必ず一方の端点 u が集合 A、もう一方の端点 v が集合 B に属するようなグラフのことです。つまり、同じ集合内の頂点同士を結ぶ辺(A-A や B-B)が一切存在しないグラフです。例として、次のようなグラフを考えてみましょう。この場合、頂点 [0, 4] を集合 A に、[1, 2, 3] を集合 B に分類できます。すべての辺は A から B、または