Home Leetcode

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:

Constraints:

To satisfy the BST property, we have to consider the values of the subtrees in relation to the root value root.

def isValid(node: Optional[TreeNode], 
			min_val: Optional[int], 
			max_val: Optional[int]) -> bool:
	 
	if not node: return True
	
	# check if root is valid
	if ((min_val is not None and node.val <= min_val) 
	 or (max_val is not None and node.val >= max_val)):
	   return False
	
	# root is valid - check if subtrees are valid
	return (isValid(node.left, min_val, node.val) 
		and isValid(node.right, node.val, max_val))

We only have to call this function from the root to check the full BST. We can pass the range as (None, None) since the root can be of any value.

def isValidBST(root: Optional[TreeNode]) -> bool:
	def isValid(node: Optional[TreeNode], 
				min_val: Optional[int], 
				max_val: Optional[int]) -> bool:
		
		if not node: return True
		
		# check if root is valid
		if ((min_val is not None and node.val <= min_val) 
		 or (max_val is not None and node.val >= max_val)):
		   return False
		
		# root is valid - check if subtrees are valid
		return (isValid(node.left, min_val, node.val) 
			and isValid(node.right, node.val, max_val))
	
	return isValid(root, None, None)

Time Complexity

The algorithm recurses down, checking every node. Notice at each node, there are constant time operations. Thus for a tree with nn nodes, the algorithm has O(n)\mathcal{O}(n) time complexity.

Space Complexity

No memory is used to store variables. However, notice that there is recursive overhead, since the algorithm recurses through the entirety of the tree before terminating at the root. Since there are nn nodes, there will be nn calls—thus the space complexity is O(n)\mathcal{O}(n).