98 validate binary search tree#28
Conversation
| node_stack.append(node) | ||
| node = node.left | ||
| node = node_stack.pop() | ||
| if node.val <= prev_val: |
There was a problem hiding this comment.
好みの範囲だと思いますが、
if not prev_value < node.val:のが理解しやすい気がします。
| <https://github.com/Fuminiton/LeetCode/pull/28/files> | ||
|
|
||
| in-order traversalを用いて書いてみるが、書けなかった。 | ||
| コードを読んでなぜそれで動くのかはわかるが、 |
There was a problem hiding this comment.
自分は簡単な深さ3くらいのBSTを用意して、再帰の動きを理解した上でループに書き直すにはどうするか考えることで何となく書けるようになりました。
具体的には、
各頂点の横にvisited(その頂点に関する処理を行う), left(現在の頂点の左をの子を見にいく), rightとメモ書きしておいて、pre-order,in-order,post-orderの走査はそれぞれvisited,left.rightをどういう順番でチェックすることになるかを追っていきました。
There was a problem hiding this comment.
たしかこのあたりから飛べるあたりで、どう書いたら少しは読みやすいか話していた気がします。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.wsy49qwpwhfr
| ```python | ||
| class Solution: | ||
| def isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
| def is_valid_bst_helper(node, low=-(sys.maxsize), high=sys.maxsize): |
There was a problem hiding this comment.
64bitの符号付き整数の最小値は-2**63となるので、
-sys.maxsize - 1としてあげた方が正確な気がします。
There was a problem hiding this comment.
-math.infのまま書いてしまっていましたが、
確かに、負の数の場合は-1してあげるほうがより正確そうです。
| return is_valid_bst_helper(node.left, low, node.val) \ | ||
| and is_valid_bst_helper(node.right, node.val, high) | ||
| return is_valid_bst_helper(root) | ||
| ``` |
There was a problem hiding this comment.
いいと思います。
範囲に収まるか確認していく方式が自分も好みでした。
in-order順にvalを返すgeneratorを使う実装も、
シンプルで直感的なのでやってみてもいいと思います。
There was a problem hiding this comment.
There was a problem hiding this comment.
generatorあまり知らなかったので、典型コメント集から飛んでみましたが
すごく直感的だったのでstep4以降でgeneratorを使った方法も実装しようと思います。
| ```python | ||
| class Solution: | ||
| def isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
| def _is_valid_bst(node, low =-(math.inf), high = math.inf): |
There was a problem hiding this comment.
関数内関数の定義は1行空けたほうが見やすいと個人的に思いました。PEP8 に関数内関数に対する直接の言及はないようですが、ロジックの単位で改行を使うことは推奨されていそうです。
There was a problem hiding this comment.
ありがとうございます。
ここどうしようか自分でも迷っていたのですが、今後は1行あけるようにします。
| if root is None: | ||
| return True | ||
|
|
||
| nodes_with_bounds = deque([(root, -(math.inf), math.inf)]) |
There was a problem hiding this comment.
-(math.inf) の () は不要そうです。() がたくさん出てくると区切りがわかりづらいので個人的にはなくてもよいものは削除したい派です。
| prev_val = -(sys.maxsize) | ||
|
|
||
| while node_stack or node is not None: | ||
| while node: |
There was a problem hiding this comment.
細かいですが、同じチェックをするときに if root is None という表現と while node という表現が混在しているのがちょっと気になりました。統一感があるとよさそうです。
| val = node.val | ||
| if not (low < val < high): |
There was a problem hiding this comment.
val は汎用的な言葉なので node.val のまま扱うほうが可読性が高そうです。(置き換えによる嬉しさは書き手側の書く量が少し減ることかなと推測しましたが、読み手側目線だととくに嬉しさがなさそうです)
また low, high も上記で使っていたような lower_bound, upper_bound とするほうがよりわかりやすい気がします。
| ```python | ||
| class Solution: | ||
| def isValidBST(self, root: Optional[TreeNode]) -> bool: | ||
| def _is_valid_bst(node, low =-(math.inf), high = math.inf): |
There was a problem hiding this comment.
値が整数なので、sys.maxsizeの方が好みですが、デカい異物の初期値であればなんでもいいので math.inf でもいいと思います。
https://leetcode.com/problems/validate-binary-search-tree/description/