Problem

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 less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than the node’s key.
  • Both the left and right subtrees must also be binary search trees.

A subtree of treeName is a tree consisting of a node in treeName and all of its descendants.

https://leetcode.com/problems/validate-binary-search-tree/

Example 1:

case1

Input: root = [2,1,3]
Output: true

Example 2:

case2

Input: root = [5,1,4,null,null,3,6]
Output: false
Explanation: The root node’s value is 5 but its right child’s value is 4.

Constraints:

  • The number of nodes in the tree is in the range [1, 10⁴].
  • -2³¹ <= Node.val <= 2³¹ - 1

Test Cases

1
2
3
4
5
6
7
8
# 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:
solution_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import pytest

import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from _utils.binary_tree import build_tree
from solution import Solution

null = None


@pytest.mark.parametrize('root, expected', [
([2,1,3], True),
([5,1,4,null,null,3,6], False),

([2,2,2], False),
([5,4,6,null,null,3,7], False),
])
class Test:
def test_solution(self, root, expected):
sol = Solution()
assert sol.isValidBST(build_tree(root)) == expected

Thoughts

直接按照中序(in-order,LNR)遍历二叉树。如果是 BST,会得到一个严格递增的序列。遍历的时候拿当前节点和前一个节点比较,如果 key 不是严格增大的就不是 BST。

可以用栈和循环替代递归。

Code

solution.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from typing import Optional


# 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:
max_val = None
stack = []
while root or stack:
if root:
stack.append(root)
root = root.left
else:
root = stack.pop()
if max_val is not None and root.val <= max_val:
return False
max_val = root.val
root = root.right

return True