Pythonで二分木を反転する方法:再帰を使った実装を解説
二分木の反転とは
二分木が与えられたとき、その左右の子ノードを入れ替えて「鏡像」のような木を作ることを二分木の反転(Invert Binary Tree)と呼びます。これはアルゴリズムの学習やコーディング面接でも頻出のトピックです。
例えば、次のような二分木があったとします。

これを反転すると、すべてのノードの左部分木と右部分木が入れ替わり、以下のような木になります。

解き方:再帰的アプローチ
この問題は再帰を使うと非常にシンプルに解けます。考え方は以下の3ステップです。
- ルートが
None(null)であれば、そのまま返す(ベースケース) - 現在のノードの左ポインタと右ポインタを入れ替える
- 左部分木と右部分木に対して再帰的に同じ処理を行う
この処理を全ノードに対して適用することで、木全体が反転されます。計算量はノード数を n とすると O(n)、空間計算量は再帰の深さに依存し、最悪の場合(偏った木)で O(n) となります。
Pythonでの実装例
それでは、実際のPythonコードを見てみましょう。
class TreeNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def make_tree(elements):
Tree = TreeNode(elements[0])
for element in elements[1:]:
insert(Tree, element)
return Tree
def height(root):
if root is None:
return 0
else:
# 左右の部分木の高さをそれぞれ計算
l_height = height(root.left)
r_height = height(root.right)
# 大きい方に1を足して返す
if l_height > r_height:
return l_height + 1
else:
return r_height + 1
def print_given_level(root, level):
if root is None:
return
if level == 1:
print(root.data, end=',')
elif level > 1:
print_given_level(root.left, level - 1)
print_given_level(root.right, level - 1)
def level_order(root):
h = height(root)
for i in range(1, h + 1):
print_given_level(root, i)
def insert(temp, data):
que = []
que.append(temp)
while len(que):
temp = que[0]
que.pop(0)
if not temp.left:
if data is not None:
temp.left = TreeNode(data)
else:
temp.left = TreeNode(0)
break
else:
que.append(temp.left)
if not temp.right:
if data is not None:
temp.right = TreeNode(data)
else:
temp.right = TreeNode(0)
break
else:
que.append(temp.right)
class Solution(object):
def invertTree(self, root):
"""
:type root: TreeNode
:rtype: TreeNode
"""
self.solve(root)
return root
def solve(self, root):
if not root:
return
# 左右の子を入れ替える
temp = root.left
root.left = root.right
root.right = temp
# 再帰的に処理を続ける
self.solve(root.left)
self.solve(root.right)
tree1 = make_tree([1, 2, 2, 3, 4, None, 3])
ob1 = Solution()
tree2 = ob1.invertTree(tree1)
level_order(tree2)コードのポイント
- TreeNodeクラス:ノードの値と左右の子への参照を持つ基本的な二分木ノードです。
- make_tree / insert関数:リスト形式の入力から二分木を構築するための補助関数です。
- height / level_order関数:結果をレベル順(幅優先順)に出力して確認するためのものです。
- Solutionクラス:
invertTreeメソッドが本体で、solveメソッドにより各ノードの左右を再帰的に入れ替えます。
実行結果
入力
[1,2,2,3,4,None,3]
出力
1,2,2,3,None,4,3,
出力を見ると、元の木のレベル順走査結果と比較して、左右の子が正しく入れ替わっていることが確認できます。
まとめ
二分木の反転は、再帰の基本を理解するのに最適な問題です。「ベースケースを明確にする」「現在のノードでの処理を定義する」「子ノードに処理を委ねる」という再帰の型を押さえれば、短いコードで美しく解くことができます。ぜひ自分でも手を動かして実装してみてください。
-
Pythonでソート済み配列を高さバランスの二分探索木に変換する方法
ソートされた配列 A が与えられたとき、そこから高さバランスの取れた二分探索木(BST)を生成することを考えます。ここで「高さバランスの取れた二分木」とは、すべてのノードにおいて、左右の部分木の深さの差が常に1以下であるような二分木のことを指します。例として、配列が [-10, -3, 0, 5, 9] の場合、出力の一例は [0, -3, 9, -10, null, 5] のようになります。解法のアプローチこの問題は、配列の中央要素をルートに選ぶというシンプルな発想で解くことができます。具体的な手順は以下の通りです。配列 A が空の場合は、Null(None)を返します。配列の中央の要素を見
-
Pythonで二分木の最大深度を求める方法|再帰を使った実装例を解説
Pythonで二分木の最大深度を求める二分木が与えられたとき、その最大深度を求める問題を考えます。木の最大深度とは、根(ルート)から葉ノードまでの最も長い経路をたどったときに通過するノード数のことです。例えば、下図のような二分木の場合、最大深度は 3 となります。解法のアプローチこの問題は再帰を使うことで、非常にシンプルに解くことができます。手順は以下のとおりです。再帰用のヘルパーメソッド solve(root, depth=0) を定義します。root が空(None)の場合は、そこまでの深さ depth をそのまま返します。それ以外の場合は、左部分木に対する solve(left, dep