From f195cbf49c6828beecd30e54614ecc1799c5d5c4 Mon Sep 17 00:00:00 2001 From: tokuhirat <54652919+tokuhirat@users.noreply.github.com> Date: Wed, 30 Jul 2025 23:07:32 +0900 Subject: [PATCH] Create 776. Split BST.md --- 776. Split BST/776. Split BST.md | 123 +++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 776. Split BST/776. Split BST.md diff --git a/776. Split BST/776. Split BST.md b/776. Split BST/776. Split BST.md new file mode 100644 index 0000000..88c8d2a --- /dev/null +++ b/776. Split BST/776. Split BST.md @@ -0,0 +1,123 @@ +# 776. Split BST +## STEP1 +- 何も見ずに解いてみる +- target 以下で最大の値を持つ node を根にしないといけないと勘違いしておかしなコードを書いた。 +- target 以下で最大の値を持つ node X を見つける。探索の最中に全ての node の値がtarget より小さい/大きい木をまとめておく。node X に親がいたら切り離し。代わりに node X の right を繋ぐ。 + +おかしいコード +```python +# 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 splitBST(self, root: Optional[TreeNode], target: int) -> List[Optional[TreeNode]]: + def add_tree_to_left(tree, tree_to_add): + if tree is None: + return tree_to_add + left_node = tree + while left_node is not None: + if left_node.left is None: + left_node.left = tree_to_add + break + left_node = left_node.left + return tree + + smaller_bst = None + greater_bst = None + node = root + while node is not None: + if node.val == target: + smaller_bst = add_tree_to_left(node, smaller_bst) + greater_bst = add_tree_to_left(greater_bst, node.right) + node.right = None + break + if node.val < target: + smaller_bst = add_tree_to_left(node, smaller_bst) + next_node = node.right + node.right = None + node = next_node + continue + if node.val > target: + greater_bst = add_tree_to_left(greater_bst, node) + next_node = node.left + node.left = None + node = next_node + return [smaller_bst, greater_bst] +``` + +- https://github.com/olsen-blue/Arai60/pull/48/files をみて理解した。 + +```python +class Solution: + def splitBST(self, root: Optional[TreeNode], target: int) -> List[Optional[TreeNode]]: + if root is None: + return [None, None] + + if root.val <= target: + smaller, greater = self.splitBST(root.right, target) + root.right = smaller + return [root, greater] + else: + smaller, greater = self.splitBST(root.left, target) + root.left = greater + return [smaller, root] +``` + +## STEP2 +### プルリクやドキュメントを参照 +- https://github.com/goto-untrapped/Arai60/pull/54#discussion_r1780641914 + - 具体例の考え方について。私も複雑な例から考えてしまっていた。 + - コードが書けて正当性について他者に説明できる理解の精度がないといけませんね。 + - while で書くパターン。 + - 番兵を使う。node_in_smaller_bst は target 以下であることがわかった中で最大の node を指す。今後見つかる target 以下のノードはこれより大きいので right に繋がないといけない。 + - smaller_bst_root = TreeNode(-math.inf), greater_bst_root = TreeNode(math.inf) と書くと番兵らしさが増しそう? + +```python +class Solution: + def splitBST(self, root: Optional[TreeNode], target: int) -> List[Optional[TreeNode]]: + node = root + smaller_bst_root = TreeNode() + node_in_smaller_bst = smaller_bst_root + greater_bst_root = TreeNode() + node_in_greater_bst = greater_bst_root + + while node is not None: + if node.val <= target: + node_in_smaller_bst.right = node + node_in_smaller_bst = node_in_smaller_bst.right + node = node.right + node_in_smaller_bst.right = None + else: + node_in_greater_bst.left = node + node_in_greater_bst = node_in_greater_bst.left + node = node.left + node_in_greater_bst.left = None + return [smaller_bst_root.right, greater_bst_root.left] +``` +- https://github.com/Mike0121/LeetCode/pull/16/files +- https://github.com/hayashi-ay/leetcode/pull/53/files +- https://github.com/Ryotaro25/leetcode_first60/pull/50/files +- いくつかPR見たが smaller/greater の組み合わせの人はいない。些細なことだが問題文にある表現を使った方が良いと思う。 + +## STEP3 +### 3回ミスなく書く +```python +class Solution: + def splitBST(self, root: Optional[TreeNode], target: int) -> List[Optional[TreeNode]]: + if root is None: + return [None, None] + + if root.val <= target: + smaller_root, greater_root = self.splitBST(root.right, target) + root.right = smaller_root + return [root, greater_root] + else: + smaller_root, greater_root = self.splitBST(root.left, target) + root.left = greater_root + return [smaller_root, root] +``` + +2分,2分,2分で3回Accept