-
Notifications
You must be signed in to change notification settings - Fork 0
Solved Arai60/108. Convert Sorted Array to Binary Search Tree #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
## Step 1. Initial Solution | ||
|
||
- BSTが何なのか分かっておらず、ただheight-balanced treeを作っていた | ||
- キューに対して次に子ノードを追加するノードを入れていくことで高さをキープする | ||
- 右が入れ終わったら左右をこのキューに入れる、という方式 | ||
|
||
```python | ||
class Solution: | ||
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: | ||
if not nums: | ||
return None | ||
root: TreeNode = TreeNode(val=nums[0]) | ||
nodes_to_add: deque[TreeNode] = deque([root]) | ||
for i in range(1, len(nums)): | ||
node = nodes_to_add.popleft() | ||
if node.left is None: | ||
node.left = TreeNode(val=nums[i]) | ||
nodes_to_add.append(node) | ||
elif node.right is None: | ||
node.right = TreeNode(val=nums[i]) | ||
nodes_to_add.append(node.left) | ||
nodes_to_add.append(node.right) | ||
return root | ||
|
||
``` | ||
|
||
- 解説を読んでBSTを理解した | ||
- 再帰で書くのがシンプル | ||
|
||
```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 sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: | ||
if not nums: | ||
return None | ||
root: TreeNode = TreeNode() | ||
middle: int = len(nums) // 2 | ||
root.val = nums[middle] | ||
root.left = self.sortedArrayToBST(nums[:middle]) | ||
root.right = self.sortedArrayToBST(nums[middle+1:]) | ||
return root | ||
``` | ||
|
||
### Complexity Analysis | ||
|
||
- 時間計算量:O(nlogn) | ||
- numsのコピーにO(n)の時間がかかる | ||
- n/2のコピーが2回, n/4のコピーが4回… | ||
- 空間計算量:O(n) | ||
- 時間と同じオーダーかと思ったがDFSで処理していくので最大でもO(n) | ||
- https://github.com/colorbox/leetcode/pull/38/files#r1939180637 | ||
|
||
## Step 2. Alternatives | ||
|
||
- 基本的には二分探索と同様の選択肢の幅がある | ||
- インデックスを管理してコピーを避ける方法 | ||
- BFSで実装したがDFSでも良い | ||
- 当たり前だが常にheight-balancedになっている必要はない | ||
- https://github.com/shintaro1993/arai60/pull/28/files#diff-5db3d349f04f651e2faacefca7e2937a523f2fd8c8b6cbd30ad1e7ed699f8d3aR104 | ||
|
||
```python | ||
class Solution: | ||
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: | ||
root: TreeNode = TreeNode() | ||
node_and_range: deque[Tuple[TreeNode, int, int]] = deque([(root, 0, len(nums))]) | ||
while node_and_range: | ||
node, left_index, right_index = node_and_range.popleft() | ||
middle_index = (left_index + right_index) // 2 | ||
node.val = nums[middle_index] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 一応、numsが空配列の場合ここでIndexErrorになりますかね。別解ではNoneを返しているので意図通りかは少し気になりました There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 空配列は問題文の条件にはないのですが、他の人のを見ると気にしていない人が多かったので書かないことにしました。 |
||
if left_index < middle_index: | ||
node.left = TreeNode() | ||
node_and_range.append((node.left, left_index, middle_index)) | ||
if middle_index + 1 < right_index: | ||
node.right = TreeNode() | ||
node_and_range.append((node.right, middle_index + 1, right_index)) | ||
return root | ||
``` | ||
|
||
- 計算量とコード量的には再帰+インデックス管理が良さそう | ||
- ヘルパー関数を使ったことがあまりなかったので使ってみる | ||
- https://github.com/hayashi-ay/leetcode/pull/29/files#diff-7e1a92af8dc65ffab400b9bf2416693d15f370a5cfb6ac37e009f85a67c03a32R23 | ||
|
||
```python | ||
class Solution: | ||
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: | ||
def sortedArrayToBSTHelper(node: TreeNode, left: int, right: int) -> TreeNode: | ||
middle = (left + right) // 2 | ||
node.val = nums[middle] | ||
if left < middle: | ||
node.left = sortedArrayToBSTHelper(TreeNode(), left, middle) | ||
if middle + 1 < right: | ||
node.right = sortedArrayToBSTHelper(TreeNode(), middle + 1, right) | ||
return node | ||
return sortedArrayToBSTHelper(TreeNode(), 0, len(nums)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TreeNode は引数で与えず中で作ってもこの場合は大丈夫でしょうかね。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 本当ですね。後からreturnしてくれば先につなげなくてもいいですね |
||
``` | ||
|
||
|
||
## Step 3. Final Solution | ||
|
||
- ヘルパー関数が気に入った | ||
- ノードを返してあげれば更に簡単になる | ||
- 閉区間や開区間でも実装してみた(以下は開区間) | ||
|
||
```python | ||
class Solution: | ||
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]: | ||
def createNode(left: int, right: int) -> TreeNode: | ||
middle = (left + right) // 2 | ||
node = TreeNode(nums[middle]) | ||
if left + 1 < middle: | ||
node.left = createNode(left, middle) | ||
if middle + 1 < right: | ||
node.right = createNode(middle, right) | ||
return node | ||
return createNode(-1, len(nums)) | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nodes_to_add という変数名で、同じノードを入れたり出したりしているのがわかりづらいと思いました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nodes_to_processとかの方が良いですかね