【Python】連結リストをジグザグ二分木に変換するプログラムの書き方
問題の概要
単方向連結リスト(片方向リンクリスト)が与えられたとき、次のルールに従って二分木へ変換することを考えます。
- 連結リストの先頭ノード(head)が、二分木のルートになります。
- それ以降の各ノードは、その値が親ノードより小さい場合は左の子に、そうでない場合は右の子になります。
たとえば、入力が [2,1,3,4,0,5] の場合、変換後の二分木は次のような「ジグザグ」形状になります。

解き方の手順
この問題は、再帰的に呼び出す関数 solve() を定義すると、シンプルに解くことができます。具体的な手順は以下の通りです。
- ノードを引数として受け取る関数
solve()を定義します。 - ノードが null(None)の場合は、None を返します。
- 受け取ったノードと同じ値を持つ新しいツリーノードを作成し、これを root とします。
- ノードの次の要素(next)が存在する場合は、値の大小によって処理を分けます。
- next の値が現在のノードの値より小さい場合:
root.left = solve(node.next)として左側に接続 - それ以外の場合:
root.right = solve(node.next)として右側に接続
- next の値が現在のノードの値より小さい場合:
- 最後に root を返します。
Pythonでの実装例
それでは、実際のコードを見てみましょう。
class ListNode:
def __init__(self, data, next=None):
self.val = data
self.next = next
def make_list(elements):
head = ListNode(elements[0])
for element in elements[1:]:
ptr = head
while ptr.next:
ptr = ptr.next
ptr.next = ListNode(element)
return head
class TreeNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def print_tree(root):
if root is not None:
print_tree(root.left)
print(root.data, end=', ')
print_tree(root.right)
class Solution:
def solve(self, node):
if not node:
return None
root = TreeNode(node.val)
if node.next:
if node.next.val < node.val:
root.left = self.solve(node.next)
else:
root.right = self.solve(node.next)
return root
ob = Solution()
L = make_list([2,1,3,4,0,5])
print_tree(ob.solve(L))
入力
[2,1,3,4,0,5]
出力
1, 3, 0, 5, 4, 2,
コードの解説と計算量
print_tree() は二分木を中順走査(In-order Traversal)で出力する関数です。「左の子 → 自分自身 → 右の子」の順に訪問するため、上記の出力では木の構造がそのまま反映されています。今回の入力では 2 → 1 → 3 → 4 → 0 → 5 の順にノードが並んでおり、値の大小比較によってすべてのノードが一方向に連なるジグザグ状の木が構築されます。
計算量については、連結リストの各ノードを一度ずつ処理するため、時間計算量は O(n) です。また、再帰呼び出しの深さがノード数に比例するため、空間計算量も再帰スタック分の O(n) となります。
-
Pythonで方向リストを使って二分木を走査するプログラム
二分木と、R(右)、L(左)、U(上)からなる文字列のリスト moves が与えられているとします。ルートから出発し、moves の各指示に従って木をたどります。R は右の子ノードへ移動、L は左の子ノードへ移動、U は親ノードへ戻ることを意味します。例えば、次のような二分木があったとします。入力が [R, R, U, L] の場合、出力は 3 になります。解決のアプローチこの問題は、通過したノードの履歴をスタック(リスト)で管理することで解決できます。手順は以下の通りです。空のリスト past を用意します。moves 内の各移動指示に対して、以下を繰り返します。まず現在のノードを past
-
Pythonで二分探索木のノードの兄弟の値を見つけるプログラム
問題概要 値 k と二分探索木が与えられます。この木では、各ノードは葉ノードであるか、必ず2つの子を持っています。値 k を持つノードを見つけ、その兄弟ノードの値を返す必要があります。 例えば、次のような二分探索木が与えられたとします。 k = 4 の場合、出力は 10 になります(4の兄弟ノードが10だからです)。 解法のアプローチ この問題は、二分探索木の性質(左の子 < 親 < 右の子)を利用することで効率的に解けます。手順は以下の通りです。 関数 util() を定義します。引数として root(現在のノード)、k(探す値)、ans(結果を格納するリスト)を受け取りま