# LeetCode Medium 106. Construct Binary Tree from Inorder and Postorder Traversal
tags: leetcode
問題
アイデア
inorderのBSTとpostorderのBSTが与えられた時に,BSTを構築しろという問題です.
木の探索順序
木を探索する際の順序として以下の図ように
- Inorder(左→根→右)
- Preorder(根→左→右)
- Postorder(左→右→根)
があります
ノードが5つの木の場合を図示すると以下の通りです
Inorderに木を走査する際は
- 基底は現在のノードが
NULL
(葉の次についているノード)であるときに終了する - 現在のノードが
NULL
でないときは左部分木に進み, 現在のノードの値をans
に入れる, 右部分木に進むということを繰り返します- これによって左の部分木のノードが先に入り, 次に右の部分木のノードが入ります
順序に注目すると
postorderの最後の要素は根となります.
inorderは左部分木→ノード→右部分木と走査するので,inorderで根の左側は左部分木,右側は右部分木です.
解法
- 上のアイデアを配列を用いて実装すると計算量が無駄にかかります
- 計算量改善のため,連想配列を用いて実装します.
postorder
の末尾から走査することで,ノード→右部分木→左部分木と見ることになります.mid
から見て,右部分木,左部分木を再帰関数rec
を使って構築していきます.low
とhigh
は走査するノードのinorder
でのindexを見ていて,これが逆転して場合,走査する範囲を超えたことを表します.
計算量
inorder
, postorder
のノードの数をそれぞれ$N$,$M$とし,木の深さを$H$とします.
Python
# Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode: inorder_dic = {} for i, val in enumerate(inorder): inorder_dic[val] = i return self.rec(0, len(inorder)-1, postorder, inorder_dic) def rec(self, low, high, postorder, inorder_dic): if low > high: return None x = TreeNode(postorder.pop()) mid = inorder_dic[x.val] x.right = self.rec(mid+1, high, postorder, inorder_dic) x.left = self.rec(low, mid-1, postorder, inorder_dic) return x