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

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


各ノードの値がそのノードの色を表す二分木を考えます。木に含まれる色は最大で2色です。ここで、ノード同士の色を何度でも入れ替えられるとき、辺でつながれた隣接ノード同士が同じ色にならないような配置が可能かどうかを判定します。

たとえば、入力が次のような木だったとします。

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

この場合の出力は True です。色を入れ替えることで、次のようにすべての隣接ノードが異なる色になる状態を作れるからです。

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

解法のアプローチ

この問題は、次の手順で解くことができます。

  • colors := 空のマップ(各色を持つノードの個数を記録)
  • prop := 空のマップ(フラグごとのノード数を記録)
  • dfs() 関数を定義する。引数は node と flag
  • node が null の場合は何もせずに return
  • colors[node の値] を 1 増やす
  • prop[flag] を 1 増やす
  • dfs(node の左の子、flag を反転した値)を呼び出す
  • dfs(node の右の子、flag を反転した値)を呼び出す
  • メイン処理では dfs(root, True) を実行し、colors と prop の値がすべて一致していれば True、そうでなければ False を返す

このアルゴリズムの鍵となるのは、木が二部グラフであるという性質です。DFSで隣接ノードに交互にフラグ(True / False)を割り当てることで、木全体を矛盾なく2つのグループに分割できます。色はノード間で自由に入れ替えられるため、各グループのサイズと各色のノード数がうまく対応づけられれば、「隣接ノードが必ず異なる色になる」という条件を満たす配置を実現できます。

それでは、理解を深めるために以下の実装を見てみましょう。

実装例

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

class Solution:
    def solve(self, root):
        colors = defaultdict(int)
        prop = defaultdict(int)

        def dfs(node, flag=True):
            if not node:
                return
            colors[node.val] += 1
            prop[flag] += 1
            dfs(node.left, not flag)
            dfs(node.right, not flag)

        dfs(root)
        return set(colors.values()) == set(prop.values())

ob = Solution()
root = TreeNode(2)
root.left = TreeNode(2)
root.right = TreeNode(2)
root.right.left = TreeNode(1)
root.right.right = TreeNode(1)
root.right.left.right = TreeNode(1)
print(ob.solve(root))

入力

root = TreeNode(2)
root.left = TreeNode(2)
root.right = TreeNode(2)
root.right.left = TreeNode(1)
root.right.right = TreeNode(1)
root.right.left.right = TreeNode(1)

出力

True

  1. Pythonで二分木が二分探索木(BST)かどうかを判定する方法

    はじめに:BSTとは何か二分木が与えられたとき、それが二分探索木(Binary Search Tree:BST)であるかどうかを判定することは、データ構造の学習やコーディング面接でよく出題される定番の問題です。BSTには以下のような重要な性質があります。左部分木に含まれるすべてのノードの値は、現在のノードの値より小さい右部分木に含まれるすべてのノードの値は、現在のノードの値より大きいこれらの性質は、木の中のすべてのノードに対して再帰的に成り立つたとえば、次のような二分木を考えてみましょう。ルート:5左の子:1右の子:9(その左の子:7、さらに左の子:6・右の子:8/右の子:10)この場合、すべ

  2. Pythonで二分木が完全二分木かどうかを判定するプログラム

    完全二分木とは二分木が与えられたとき、その木が完全二分木(complete binary tree)であるかどうかを判定することを考えます。完全二分木とは、最後のレベルを除くすべてのレベルがノードで埋め尽くされており、最後のレベルのノードはすべて可能な限り左側に寄せられている二分木のことです。例えば、次のような二分木が入力として与えられた場合、出力は True になります。アルゴリズム(BFSによる判定方法)この問題は、幅優先探索(BFS)を使って効率的に解けます。木をレベル順に走査し、初めて空のノード(None)が出現した後に再びノードが出現したら、その木は完全二分木ではないと判断できます。