Skip to content

Conversation

fhiyo
Copy link
Owner

@fhiyo fhiyo commented Jun 24, 2024

class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
def to_bst(begin: int, end: int) -> Optional[TreeNode]:
if begin == end:

Choose a reason for hiding this comment

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

個人的には、二分探索の終了条件は不等号もつけた方が分かりやすいと思います。
趣味の範囲かもしれません。

def to_bst(begin: int, end: int) -> Optional[TreeNode]:
if begin == end:
return None
mid = (begin + end) // 2

Choose a reason for hiding this comment

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

単語は略さない方が良いと思いました。

Copy link
Owner Author

Choose a reason for hiding this comment

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

何となくmidは市民権を得ている感覚があったのですが、微妙ですかね。
わりとしっくり来ているのでどうしようかな...もうちょっと試して決めてみようかと思います

Copy link

Choose a reason for hiding this comment

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

mid という形容詞はありますね。
https://www.merriam-webster.com/dictionary/mid

if not nums:
return None
sentinel = TreeNode()
parent_with_range_stack = [(sentinel, 0, len(nums), True)]
Copy link

@sakupan102 sakupan102 Jun 25, 2024

Choose a reason for hiding this comment

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

最初にsentinelの左側にnodeをくっつけるのがほんの少しだけ気になりました。
これやるなら最初の処理をwhileの外で行うとかですかね。

stack.append(('back', node_ref, left_node_ref, right_node_ref, begin, end))
stack.append(('go', left_node_ref, Box(None), Box(None), begin, mid))
stack.append(('go', right_node_ref, Box(None), Box(None), mid + 1, end))
node_ref.value.left = left_node_ref.value

Choose a reason for hiding this comment

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

ここの処理が行きがけでも行われるのが少し違和感があります。
個人的には
行き→下にTreeNodeを作るようにたのむ
帰り→下で作ったTreeNodeを繋ぎ合わせる
この方法のほうが再帰との対応が良いかと思いました。

Copy link
Owner Author

Choose a reason for hiding this comment

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

すみません、あまりイメージが湧かず...質問させてください。

ここの処理が行きがけでも行われるのが少し違和感があります。

これはどこの部分になるでしょうか?

行き→下にTreeNodeを作るようにたのむ
帰り→下で作ったTreeNodeを繋ぎ合わせる

もし良ければでいいんですが、コードがどんな感じになるか書いていただけないでしょうか?

Choose a reason for hiding this comment

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

イメージこんな感じです
まあelseを足しただけですが...

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        root_ref = Box(None)
        stack = [('go', root_ref, Box(None), Box(None), 0, len(nums))]
        while stack:
            go_back, node_ref, left_node_ref, right_node_ref, begin, end = stack.pop()
            if go_back == 'go':
                if begin == end:
                    continue
                mid = (begin + end) // 2
                node_ref.value = TreeNode(nums[mid])
                stack.append(('back', node_ref, left_node_ref, right_node_ref, begin, end))
                stack.append(('go', left_node_ref, Box(None), Box(None), begin, mid))
                stack.append(('go', right_node_ref, Box(None), Box(None), mid + 1, end))
            else: #go_back == 'back'
                node_ref.value.left = left_node_ref.value
                node_ref.value.right = right_node_ref.value
        return root_ref.value

このelseがないとgo_back === 'go'のときも左右のノードをつなげる処理が行われていて、行きと帰りで違う処理をしている理由があまりないかなと思いました。

Copy link
Owner Author

Choose a reason for hiding this comment

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

あーっわかりましたごめんなさい...これ if go_back == 'go' のブロックの最後にcontinue付けてるつもりでいました。
たしかにおっしゃる通り今のコードだとgoの処理でも左右につなげてますね、失礼しました 🙇

root_ref = Box(None)
stack = [('go', root_ref, Box(None), Box(None), 0, len(nums))]
while stack:
go_back, node_ref, left_node_ref, right_node_ref, begin, end = stack.pop()

Choose a reason for hiding this comment

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

自分だけかもしれませんが、refが何を参照しているかが少し戸惑ったのですが、Boxを利用される場合はよくある書き方でしょうか?node, left_child, right_childとかでも良い気がしました。見当違いでしたらすみません。

Copy link
Owner Author

Choose a reason for hiding this comment

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

よくあるのかは分からないんですが、個人的にはPythonのような動的型付け言語で _ref の接尾辞を書かずnodeみたいに書くと、TreeNodeなのかTreeNodeを指すコンテナなのかが分からず書きにくくなる印象がありました。

スタックに直した版。node_and_ranges_stackにappendする値を間違えており (right側で(node.right, mid, end)を積むようにしていた)、図を書くまで何が問題か分からず時間がかかった。
こういう勘違いはこのアルゴリズムで何をしているかきちんと分かっており言語化できればあまり起こらないと思うので、理解不足なのだろう。

node_and_ranges_stackはもう少しいい名前があるかも。Pythonでは問題ないがendはちょっとキーワード感あるかもしれない?

Choose a reason for hiding this comment

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

冗長に感じる場合、_stackは省略しても良いのかなと思いました。(好みの問題かもです。)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants