Skip to content
Open
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
123 changes: 123 additions & 0 deletions 776. Split BST/776. Split BST.md
Original file line number Diff line number Diff line change
@@ -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)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

smarller_root greater_rootとする方が分かりやすいと感じました。

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 で書くパターン。
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

以前小田さんから「再帰とループの中間を念頭において、対応関係から相互に変換できるようにしておくといいでしょう。」とコメントをいただいたことがございます。リンク先にコードもございます🙇
Ryotaro25/leetcode_first60#50 (comment)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

再帰とループの対応は考えてましたが中間というものは考えたことがありませんでした。
Python では書きにくそうですね。コメントありがとうございます。

- 番兵を使う。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]
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/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