-
Notifications
You must be signed in to change notification settings - Fork 0
98. Validate Binary Search Tree #30
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,43 @@ | ||
| ## step1 | ||
| - 最後にleft,rightに行った箇所が重要な気がした | ||
| - 常に下記を満たす必要がある | ||
| - 最後にleftに行った箇所のval未満でなければならない | ||
| - 最後にrightに行った箇所のvalを超える値でなければならない | ||
| - 幅優先探索をする | ||
| - 管理するnodeとless_than,more_thanを管理すれば良さそう | ||
| - NoneはTrueなのかFalseなのか | ||
| - `The number of nodes in the tree is in the range [1, 10^4].`となっているが、型はOptional | ||
| - 一旦Noneも入る想定にする | ||
| - 個人的にはFalseにしたい | ||
| - Trueの判定を行なった後でNoneのことを考慮したくない | ||
| - 10分ほどでかけた | ||
|
|
||
| ## step2 | ||
| - 再帰でも書ける気はする | ||
| - どれか1つでもFalseになったらダメなので`and`で繋いでいけば良い? | ||
| - 一旦書いてみる | ||
| - 10分ほどで書けたがhelperの子の有無をもっと上手く書けるかもしれない | ||
| - 数字の判定を先に書くことでFalseが入った場合に早めに打ち切られるようにした | ||
| - 他の人のコードを見る | ||
| - https://github.com/mamo3gr/arai60/pull/26 | ||
| ``` | ||
| ところで `root is None` なときはどちらなんだろうか。もはや木ですらないし、比較する値もないが…。 | ||
| →Geminiと議論したところ、空の木は二分探索木としてよいみたい。理屈としては、ノードがひとつだけの木を考えたとき、そのsubtreeも二分探索木なはずで、subtree=空の木だから。 | ||
| Web上の資料を探してもらったが、明確に定義としてそう書いてあるものは見つけられなかった。 | ||
| ``` | ||
| - 同じ部分が気にできていたが、結論は違っていた。`そのsubtreeも二分探索木なはず`これは確かに | ||
| - `何が分かりにくいかを言語化しておく。`こういう姿勢を持てるようになりたい | ||
| - `inf`をmath.infでも書けるのは知っておく | ||
| - https://github.com/huyfififi/coding-challenges/pull/39/changes#diff-ac2b937f26131bdaf8a2c0d3709d0befa4ae53c7efb9f6efbceb62567acc9c75 | ||
| - `if node is None: continue`これは選択肢になかった。子がNoneの場合でも追加しておいて、チェックする際にcontinueする方法 | ||
| - https://github.com/plushn/SWE-Arai60/pull/28/changes | ||
| - `yield_from`知らなかった | ||
| - https://docs.python.org/3.14/reference/expressions.html#grammar-token-python-grammar-yield_from | ||
| - 再帰に苦手意識があるので組み合わさると結構読む時に身構えてしまう | ||
| - https://github.com/Kaichi-Irie/leetcode-python/pull/29/changes | ||
| - `Noneチェックはpop後にやる他、append前にやる方法もあります。一応速度の面ではappend前にやった方がわずか速いことになりますが、趣味の範囲だと思います。pop後にやる方が大抵コードはシンプルになる気がします。`先ほどの気づきが一般化されて言語化されていた。このように言語化して理解していきたい。 | ||
|
|
||
| ## step3 | ||
| - step1の変数名を修正した | ||
| - 処理時にNoneの判定をするようにした | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # | ||
| # @lc app=leetcode id=98 lang=python3 | ||
| # | ||
| # [98] Validate Binary Search Tree | ||
| # | ||
|
|
||
| # @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 isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
| if root is None: | ||
| return False | ||
|
|
||
| more_than = -float("inf") | ||
| less_than = float("inf") | ||
| level_nodes_with_range = [(root, more_than, less_than)] | ||
|
|
||
| while level_nodes_with_range: | ||
| next_level_nodes_with_range = [] | ||
| for node, more_than, less_than in level_nodes_with_range: | ||
| is_valid_bst_node = more_than < node.val < less_than | ||
|
|
||
| if not is_valid_bst_node: | ||
| return False | ||
|
|
||
| if node.left is not None: | ||
| next_level_nodes_with_range.append((node.left, more_than, node.val)) | ||
| if node.right is not None: | ||
| next_level_nodes_with_range.append( | ||
| (node.right, node.val, less_than) | ||
| ) | ||
| level_nodes_with_range = next_level_nodes_with_range | ||
|
|
||
| return True | ||
|
|
||
|
|
||
| # @lc code=end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # | ||
| # @lc app=leetcode id=98 lang=python3 | ||
| # | ||
| # [98] Validate Binary Search Tree | ||
| # | ||
|
|
||
| # @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 isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
| if root is None: | ||
| return False | ||
|
|
||
| def helper(node: TreeNode, more_than: int, less_than: int): | ||
| if node.left is None and node.right is None: | ||
| return more_than < node.val < less_than | ||
|
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. https://github.com/xbam326/leetcode/pull/30/changes#r2829373715 のパターンがスッキリしそうですが、このままいくなら、何度も出てくる条件 |
||
| if node.left is None: | ||
| return more_than < node.val < less_than and helper( | ||
| node.right, node.val, less_than | ||
| ) | ||
| if node.right is None: | ||
| return more_than < node.val < less_than and helper( | ||
| node.left, more_than, node.val | ||
| ) | ||
|
|
||
| return ( | ||
| more_than < node.val < less_than | ||
| and helper(node.right, node.val, less_than) | ||
| and helper(node.left, more_than, node.val) | ||
| ) | ||
|
|
||
| return helper(root, -float("inf"), float("inf")) | ||
|
|
||
|
|
||
| # @lc code=end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # | ||
| # @lc app=leetcode id=98 lang=python3 | ||
| # | ||
| # [98] Validate Binary Search Tree | ||
| # | ||
|
|
||
| # @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 isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
| if root is None: | ||
| return True | ||
|
|
||
| more_than = -float("inf") | ||
|
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. min/max や low/high だと境界を含むように聞こえるから避けられたのだと予想しますが、more_than/less_than は少し動詞っぽい響きで、特定の値を示す時にはあまり使用されないように思います。 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. low/highとかlower/upperに |
||
| less_than = float("inf") | ||
| current_level_nodes_with_range = [(root, more_than, less_than)] | ||
|
|
||
| while current_level_nodes_with_range: | ||
| next_level_nodes_with_range = [] | ||
| for node, more_than, less_than in current_level_nodes_with_range: | ||
| if node is None: | ||
| continue | ||
|
|
||
| valid_bst_node = more_than < node.val < less_than | ||
|
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 not valid_bst_node: | ||
| return False | ||
|
|
||
| next_level_nodes_with_range.append((node.left, more_than, node.val)) | ||
| next_level_nodes_with_range.append((node.right, node.val, less_than)) | ||
|
|
||
| current_level_nodes_with_range = next_level_nodes_with_range | ||
|
|
||
| return True | ||
|
|
||
|
|
||
| # @lc code=end | ||
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.
step 2 で考察されていましたが、helperやqueueに
Noneを積むのを許容して、またrootがNoneの時Trueを返してしまえば、これらの場合分けは要らなくなりそうですね。