Pythonで二分木の指定した垂直レベルがソートされているかどうかを判定する方法
問題の概要
二分木が与えられたとき、指定された垂直レベル(vertical level)に属するノードの値が昇順にソートされているかどうかを判定する問題です。垂直レベルとは、木を横から見たときに同じ縦位置に並ぶノードのグループを指し、ルートのレベルを 0 とすると、左へ移動するごとに -1、右へ移動するごとに +1 となります。
なお、2つのノードが画面上で重なって見える場合でも、それぞれが属するレベル内での並び順がソートされていればよいものとします。
例として level = -1 を指定した場合、そのレベルに含まれる要素は「3, 7」であり、昇順に並んでいるため、出力は True になります。

解法のアプローチ:BFS(幅優先探索)を活用
この問題は、BFS(幅優先探索)を使うことで効率的に解けます。deque(両端キュー)を利用して各ノードとその垂直レベルをペアで管理しながら走査し、対象レベルのノード値が常に直前の値以上であることを確認していきます。
アルゴリズムの手順
- ルートが null の場合は True を返す
- previous_value を負の無限大(INT_MIN)で初期化する
- current_level を 0 に初期化する
- current_node を値 0 の新しいツリーノードとして初期化する
- deque 型のキュー q を定義する
- (root, 0) を q の末尾に追加する
- q が空になるまで以下を繰り返す:
- current_node に q[0][0] を代入する
- current_level に q[0][1] を代入する
- q の左端から要素を取り除く
- current_level が指定された level と一致する場合:
- previous_value <= current_node.val であれば、previous_value を current_node.val で更新する
- そうでなければ False を返す
- current_node.left が存在すれば、(current_node.left, current_level - 1) を q の末尾に追加する
- current_node.right が存在すれば、(current_node.right, current_level + 1) を q の末尾に追加する
- ループが完了したら True を返す
Pythonでの実装例
それでは、実際のコードを見てみましょう。
from collections import deque
from sys import maxsize
INT_MIN = -maxsize
class TreeNode:
def __init__(self, key):
self.val = key
self.left = None
self.right = None
def are_elements_sorted(root, level):
if root is None:
return True
previous_value = INT_MIN
current_level = 0
current_node = TreeNode(0)
q = deque()
q.append((root, 0))
while q:
current_node = q[0][0]
current_level = q[0][1]
q.popleft()
if current_level == level:
if previous_value <= current_node.val:
previous_value = current_node.val
else:
return False
if current_node.left:
q.append((current_node.left, current_level - 1))
if current_node.right:
q.append((current_node.right, current_level + 1))
return True
root = TreeNode(2)
root.left = TreeNode(3)
root.right = TreeNode(6)
root.left.left = TreeNode(8)
root.left.right = TreeNode(5)
root.left.right.left = TreeNode(7)
level = -1
print(are_elements_sorted(root, level))入力
root = TreeNode(2)
root.left = TreeNode(3)
root.right = TreeNode(6)
root.left.left = TreeNode(8)
root.left.right = TreeNode(5)
root.left.right.left = TreeNode(7)
出力
True
計算量の目安
このアルゴリズムは各ノードを一度だけ訪問するため、時間計算量は O(n) です。また、キューには最大で木の幅に相当するノードが格納されるため、空間計算量も O(n) となります(n は二分木のノード総数)。BFS を使うことで、深さ優先探索のように再帰スタックを意識することなく、レベルごとの値を順番に検証できるのがポイントです。
-
Pythonで二分木を反転する方法:再帰を使った実装を解説
二分木の反転とは二分木が与えられたとき、その左右の子ノードを入れ替えて「鏡像」のような木を作ることを二分木の反転(Invert Binary Tree)と呼びます。これはアルゴリズムの学習やコーディング面接でも頻出のトピックです。例えば、次のような二分木があったとします。これを反転すると、すべてのノードの左部分木と右部分木が入れ替わり、以下のような木になります。解き方:再帰的アプローチこの問題は再帰を使うと非常にシンプルに解けます。考え方は以下の3ステップです。ルートが None(null)であれば、そのまま返す(ベースケース)現在のノードの左ポインタと右ポインタを入れ替える左部分木と右部分木
-
Pythonでソート済み配列を高さバランスの二分探索木に変換する方法
ソートされた配列 A が与えられたとき、そこから高さバランスの取れた二分探索木(BST)を生成することを考えます。ここで「高さバランスの取れた二分木」とは、すべてのノードにおいて、左右の部分木の深さの差が常に1以下であるような二分木のことを指します。例として、配列が [-10, -3, 0, 5, 9] の場合、出力の一例は [0, -3, 9, -10, null, 5] のようになります。解法のアプローチこの問題は、配列の中央要素をルートに選ぶというシンプルな発想で解くことができます。具体的な手順は以下の通りです。配列 A が空の場合は、Null(None)を返します。配列の中央の要素を見