Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
## step1
- `preorder`,`inorder`がわからなかったのでChatGPTに聞いた。なんとなく思い出した。
preorder: 根 → 左部分木 → 右部分木
inorder: 左部分木 → 根 → 右部分木
- 上の流れを見るとpreorderの先頭は常に現在のrootになっているのでそれをinorderで見つけるようにするとかすればいいのかもしれない
- step1. rootを見つける
- step2. leftを見つける
- preorderのrootの右隣がある場合はleftが存在
- inorderのrootが出てきたところまでの中と一致するかどうか
- step3. rightを見つける
- inorderのrootの右隣が存在する場合はrightが存在
- `preorder and inorder consist of unique values.`この条件が無い場合はめちゃ難しくなりそう
- 配列は1 <= preorder.length <= 3000なのでNoneの場合はなし
- 15分ほどで解けたがこれを分かりやすく読みやすく書くのは難しそう
- 値がuniqueではない場合を考えたが、エラーが出たら、rootのindexを見る際に+1番目を確認するという場当たり的なものしか浮かばなかった


## step2
- 時間計算量は最悪O(N^2)(全部left)で最良でO(N)(全部right),空間計算量はO(N)
- あらかじめinorderでvalue_to_indexを作っておくと常にO(N)にできる
- 他の人のコードをみる
- https://github.com/plushn/SWE-Arai60/pull/29/changes
- stackでの実装も可能
- step1の`mid`という変数名は気になった(真ん中でない場合もあるため)rootとかparentとかの方が個人的にはしっくりくる
- step2の実装時に`TreeNode()`で初期化して後からvalを設定していくところも若干抵抗があった
- 最後まで読まないとこれで問題ないかどうかがわからないから
- https://github.com/mamo3gr/arai60/pull/28/changes
- `再帰で次に渡す配列は、コピーではなくインデックスにすると、メモリ使用量が減らせる`自分の解法は配列をcopyしていっているため空間計算量はO(N)ではなく、O(N^2)になっていた
- step1のコード見やすかった。下記は変数にした方が認知負荷を減らせそう。あとreturnの部分も最後に組み立てるイメージが湧いてわかりやすかった。
```
inorder_left = inorder[:root_index]
inorder_right = inorder[root_index + 1 :]

preorder_left = preorder[1 : len(inorder_left) + 1]
preorder_right = preorder[len(inorder_left) + 1 :]
```
- dataclassを自分から使えないので選択肢に入れたい
- 再帰でないやり方もあるが今回は自分としては再帰の方がしっくりきた
- `インデックスの操作に苦戦する。いつまで経っても苦手だ、これ。`自分も毎回苦労しており、特にsliceの含む含まないをCLIの対話モードで確認しているが早く抜け出したい
- `array.array` を使うと、スライスをコピーしなくても書ける。
- https://github.com/Yoshiki-Iwasa/Arai60/pull/33#discussion_r1688357607
- https://docs.python.org/3.13/library/array.html
- `array.array`と番兵の部分が難しくて消化不良だが後から見返す
- https://github.com/naoto-iwase/leetcode/pull/34
- 実装2のelseからが何をしているのかがわからなかった。。。
- だいぶ消化不良だが、後からまた戻ってくるようにする
- step2ではdictに入れてindexの探索をO(N)でできるように改良する部分だけ対応する
- しようと思ったがそうすると再帰で配列のsliceを渡せなくなり難しいので諦める

## step3

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
# @lc app=leetcode id=105 lang=python3
#
# [105] Construct Binary Tree from Preorder and Inorder Traversal
#

# @lc code=start
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
root_val = preorder[0]
root = TreeNode(preorder[0])
root_index_at_inorder = inorder.index(root_val)

has_left = root_index_at_inorder != 0
if has_left:
root.left = self.buildTree(
preorder[1 : root_index_at_inorder + 1],
inorder[:root_index_at_inorder],
)

has_right = root_index_at_inorder != len(inorder) - 1
if has_right:
root.right = self.buildTree(
preorder[root_index_at_inorder + 1 :],
inorder[root_index_at_inorder + 1 :],
)

return root


# @lc code=end
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# @lc app=leetcode id=105 lang=python3
#
# [105] Construct Binary Tree from Preorder and Inorder Traversal
#

# @lc code=start
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right


class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
root_val = preorder[0]
root = TreeNode(preorder[0])
root_index_at_inorder = inorder.index(root_val)

has_left = root_index_at_inorder != 0
if has_left:
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/inorder が空かどうかをチェックすることで、少しシンプルにできそうです。

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        if not preorder:
            return None

        root_val = preorder[0]
        root = TreeNode(preorder[0])
        root_index_at_inorder = inorder.index(root_val)

        root.left = self.buildTree(
            preorder[1 : root_index_at_inorder + 1],
            inorder[:root_index_at_inorder],
        )

        root.right = self.buildTree(
            preorder[root_index_at_inorder + 1 :],
            inorder[root_index_at_inorder + 1 :],
        )

        return root

root.left = self.buildTree(
preorder[1 : root_index_at_inorder + 1],
inorder[:root_index_at_inorder],
)

has_right = root_index_at_inorder != len(inorder) - 1
if has_right:
root.right = self.buildTree(
preorder[root_index_at_inorder + 1 :],
inorder[root_index_at_inorder + 1 :],
)

return root


# @lc code=end