diff --git a/98. Validate Binary Search Tree/memo.md b/98. Validate Binary Search Tree/memo.md new file mode 100644 index 0000000..7dd6b76 --- /dev/null +++ b/98. Validate Binary Search Tree/memo.md @@ -0,0 +1,101 @@ + +## step1: +ひとまずdfsで一番下の根からvalidateしていって再帰的にnode.right, node.leftに対してnodeがvalidかを判別していく。まずnode.right, node.leftがvalidである必要があるがそこはそれぞれをvalidateする際に早期にFalseをマークしておいて、すべてvalidateが終わった時にそのマークがFalseであるかで判断する。nodeがvalidであるかを判別するためにはnode.rightの最小値より小さく、node.leftの最大値より大きい必要がある。そこでdfs関数で判別したnodeのsmallest, biggestなnumberを返すようにする。葉に到達した際には必ずその根をvalidにする必要があるのでsmallestに無限大を、biggestにマイナス無限大を返すようにする。しかし、そうするとその根のnodeのleftのbiggestがマイナス無限大、rightのsmallestが無限大になってsmallest, biggestの更新が正しく行われずにvalidationが常にTrueになってしまう。そこでmin(node.val, smallest_l), max(node.val, biggest_r)を常に判断して返すようにしたが、これを葉付きのノード以外に毎回行うのは効率が悪い気がした。 +### code +```python +class Solution: + # let me think of solving this using dfs + # when in node A, if A.val is greater than biggest val of A.left tree and smaller than smallest val of A.right tree, A is binary tree + # ↑ in this case, A.right and A.left must be valid binary trees as well, so I'm gonna validate both in advance using dfs and return False early + + # when judged that node A tree is valid, I validate the upper node B. then, if A is B.left, the beggist val of A tree is needed, and if A is B.right, the smallest val of A is needed. So both the smallest and the biggest val have to be stored. + def isValidBST(self, root: Optional[TreeNode]) -> bool: + is_valid = True + + def dfs(node): + nonlocal is_valid + if not node: + return float('inf'), -float('inf') + smallest_l, biggest_l = dfs(node.left) + smallest_r, biggest_r = dfs(node.right) + if not (biggest_l < node.val < smallest_r): + is_valid = False + return min(node.val, smallest_l), max(node.val, biggest_r) + + _, _ = dfs(root) + return is_valid +``` +他の人のコードも読んでみる。 +https://github.com/h-masder/Arai60/pull/31/changes#diff-348997c4e487fecb306108a0041036c236327dcee8c3a97a3c11fbd62a2c74f7R1:~:text=%2D-,%E5%86%8D%E5%B8%B0,-%E3%82%92%E4%BD%BF%E3%82%8F +この人はiterative dfsで解いているが、親が子に対してlower < child.val < upperである制約を課して、それを破れば早期Falseを返すようにしている。lowerかupperがNoneの場合はそれは制約がないということである。これはdfs関数で書いてないので早期リターンしやすい。 +### code +```python +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + if root is None: + return True + + node_and_ranges = [(root, None, None)] + while node_and_ranges: + node, lower, upper = node_and_ranges.pop() + if node is None: + continue + if lower is not None and node.val <= lower: + return False + if upper is not None and upper <= node.val: + return False + + node_and_ranges.append((node.left, lower, node.val)) + node_and_ranges.append((node.right, node.val, upper)) + return True +``` + +## step2: +個人的にNone判定よりmath.infでやった方がNone判定のif文がなくなり見やすいのでmath.infを使う。 +### code +```python +import math +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + node_and_range = [] + node_and_range.append([root, math.inf, -math.inf]) + while node_and_range: + node, upper, lower = node_and_range.pop() + if not node: + continue + if node.val <= lower: + return False + if node.val >= upper: + return False + node_and_range.append([node.right, upper, node.val]) + node_and_range.append([node.left, node.val, lower]) + + return True +``` + +## step3: +### code +```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 +import math +# let me solve this with dfs +# the left must be less than parent.val and bigger than smallest val of ancestor +# the right must be bigger than parent.val and smaller than biggest val of ancestor +class Solution: + def isValidBST(self, root: Optional[TreeNode]) -> bool: + node_and_range = [[root, -math.inf, math.inf]] + while node_and_range: + node, lower, upper = node_and_range.pop() + if not node: + continue + if not lower < node.val < upper: + return False + node_and_range.append([node.left, lower, node.val]) + node_and_range.append([node.right, node.val, upper]) + return True +```