98. Validate Binary Search Tree
## description
## 98. Validate Binary Search Tree
Given the root of a binary tree, determine if it is a valid binary search tree (BST).
A valid BST is defined as follows:
- –The left subtree of a node contains only nodes with keys strictly less than the node's key.
- –The right subtree of a node contains only nodes with keys strictly greater than the node's key.
- –Both the left and right subtrees must also be binary search trees.
Example 1:
1Input: root = [2,1,3]
2Output: trueExample 2:
1Input: root = [5,1,4,null,null,3,6]
2Output: false
3Explanation: The root node's value is 5 but its right child's value is 4.- –The number of nodes in the tree is in the range [1, 104].
- –-231 <= Node.val <= 231 - 1
Constraints:
## notes
### Intuition
A node is valid when it is in the range of values that is decided by it's ancestors. When going deeper, the range is updated. For the root, the range starts with (-inf, inf), going left upper bound is updated, going right lower bound is updated.
### Implementation
This problem can be solved with DFS. We start by defining our recursive function that takes in a node and the left and right bounds. If the node is None, that is valid node, we can return True. Otherwise, we check if the value is NOT in the range and early return false. Finally, we call the function recursively on left AND right with the updates bounds. For the left node, the lower bound stays the same but the upper bound is updated to the current value. For the right node, the lower bound is updated to the current value and the upper bound stays the same.
Finally, we call the recursive function on the root with -inf, inf as our bounds (using sys.maxsize or float("inf")/float("-inf')).
- –Time: O(n), we visit each node, at most, once.
- –Space: O(n), recursive call stack
### Complexity
## solution
1import sys
2from typing import Optional
3from lcutils import TreeNode
4
5# Definition for a binary tree node.
6# class TreeNode:
7# def __init__(self, val=0, left=None, right=None):
8# self.val = val
9# self.left = left
10# self.right = right
11class Solution:
12 def isValidBST(self, root: Optional[TreeNode]) -> bool:
13 def valid(node: Optional[TreeNode], left: int, right: int) -> bool:
14 if not node:
15 return True
16 if not (left < node.val < right):
17 return False
18 return valid(node.left, left, node.val) and valid(node.right, node.val, right)
19
20 max_int = sys.maxsize - 1
21 return valid(root, -max_int, max_int)
22
23
24if __name__ == "__main__":
25 # Include one-off tests here or debugging logic that can be run by running this file
26 # e.g. print(solution.two_sum([1, 2, 3, 4], 3))
27 solution = Solution()
28 print("hello world")
29