Skip to content

105 construct binary tree from preorder and inorder traversal - #29

Open
tarinaihitori wants to merge 3 commits into
mainfrom
105-construct-binary-tree-from-preorder-and-inorder-traversal
Open

105 construct binary tree from preorder and inorder traversal#29
tarinaihitori wants to merge 3 commits into
mainfrom
105-construct-binary-tree-from-preorder-and-inorder-traversal

Conversation

@tarinaihitori

Copy link
Copy Markdown
Owner

preorder_index = 0

def build_tree_helper(left, right):
nonlocal preorder_index

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

副作用のある関数は避けたほうが無難という話があります。

https://discord.com/channels/1084280443945353267/1201211204547383386/1247145320098566144

olsen-blue/Arai60#29 (comment)

```python
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
value_to_inorder_index = {value:index for index, value in enumerate(inorder)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この程度の内包表記であればすんなり読めると思います。
コロンの後は空白を入れた方がいいと思います。

<https://github.com/Fuminiton/LeetCode/pull/29>

Python勢のコードを読んでいて思ったのだが、
inorderの値とインデックスのマップを作るときに、私は内包表記で一行で書きたくなるが、

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

横長になることを避けてあまり使わないイメージがあります。m*nのgridを作るくらいなら内包表記使いたくなる気がするので。

return root

return build_tree_helper(0, len(inorder))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

いいと思います。
ループへの書き換えもやっておくと、BSTの走査順に関する理解が深まると思うので、やってもいいと思います。

```

inorderでの頭からの構築
まだ右子が確定していないノードをスタックに積むことで、順序情報(preorderのインデックス順)に基づいた構築をしている?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inorder の順にノードが箱から出てくるとします。

あるノード node が出てきたとします。node.left はいるならばもうでているけれども、どこかに宙ぶらりんのはずです。node.right はまだ出てきていません。

node.left.right はいるとしたら、もう出ています。しかし、node.left が出た後に出ていて、いま、node が出るまでは、どこにつくか分からなかったはずです。
どうしてくっつくかが分かったかというと、node の inorder_index ですね。これよりも前のやつは全部回収しないといけないんですよ。

そうすると、もう一つ容器が必要な事が分かります。籠とでも呼びましょう。籠には「left は埋まったが right がまだなノード」がすべて入っています。そして、さっきの node が出てくると、.left の下にあるもの、つまり、preorder で後ろになるものを籠からすべて取り出し、鎖状にしてぶら下げます。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

鎖状にぶら下げる方法は、preorder で後ろになる順から .right で繋いでいきます。で、全体を node.left につなぎます。
これを扱いやすい構造は stack です。

あとは、最後、箱が空になったときには、籠の中にいろいろはいっているものを追い出す必要があります。

これは、番兵を使って preorder の場所が -1 よりも大きいものを出してくるとすれば、すべてが飛び出してくるはずです。

value_to_inorder_index = {value:index for index, value in enumerate(inorder)}
preorder_index = 0

def build_subtree(left, right):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left, right が何を指すのかがわかるような関数名にしたい気がします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants