From 62c670bfcc92d1502a2996605065e2d5df49d5dd Mon Sep 17 00:00:00 2001 From: Masakuni Date: Thu, 19 Feb 2026 20:13:16 +0900 Subject: [PATCH 1/2] step1 --- .../memo.md | 21 +++++++++++ .../step1.py | 37 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md create mode 100644 problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step1.py diff --git a/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md new file mode 100644 index 0000000..c0a9a13 --- /dev/null +++ b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md @@ -0,0 +1,21 @@ +## 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 + +## step3 + diff --git a/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step1.py b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step1.py new file mode 100644 index 0000000..1eb1b47 --- /dev/null +++ b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step1.py @@ -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 From 2174b3310095555a544aaa2938f000b972f3a1fc Mon Sep 17 00:00:00 2001 From: Masakuni Date: Sun, 22 Feb 2026 12:48:09 +0900 Subject: [PATCH 2/2] step2 --- .../memo.md | 30 ++++++++++++++ .../step2.py | 39 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step2.py diff --git a/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md index c0a9a13..5e3d9fe 100644 --- a/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md +++ b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/memo.md @@ -16,6 +16,36 @@ inorder: 左部分木 → 根 → 右部分木 ## 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 diff --git a/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step2.py b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step2.py new file mode 100644 index 0000000..cc02ccb --- /dev/null +++ b/problems/105.construct-binary-tree-from-preorder-and-inorder-traversal/step2.py @@ -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: + 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