98 - 验证二叉搜索树 - python + Java

60 阅读2分钟

给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:
    2
   / \
  1   3
输出: true

示例 2:

输入:
    5
   / \
  1   4
     / \
    3   6
输出: false
解释: 输入为: [5,1,4,null,null,3,6]。
     根节点的值为 5 ,但是其右子节点值为 4 

二叉树遍历性质的应用:根据二叉搜索树的定义以及二叉树的中序遍历知道,它的中序遍历结果是升序排列的,因此我们只需要得到中序遍历结果,然后验证是否是升序排列即可。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isValidBST(self, root: TreeNode) -> bool:
        res = []
        def inOrder(root):
            if root == None:
                return None
            inOrder(root.left)
            res.append(root.val)
            inOrder(root.right)

        inOrder(root)
		
		# 如果二叉树中包含相同val的节点,或者中序遍历的结果不是升序,那么不是合法的二叉搜索树
        if len(set(res)) != len(res) or sorted(res) != res:
            return False
        else:
            return True
        

上面采用了先中序遍历获取给定二叉树的遍历结果,然后根据二叉搜索树中序遍历结果为升序排列的性质,判断遍历结果是否满足来决定给定二叉树的合法性。

其实,我们只需一个临时节点preNode来记录当前遍历节点的前一个节点即可,在中序遍历的过程中进行判断,而无需额外的存储空间:

  • 如果preNodenull,表示此时遍历的是左子树的最左节点,直接将其赋给preNode,即preNode = root
  • 否则,判断当前遍历的节点valpreNode.val的大小情况。如果root.val < preNode.val,那么必然不是合法的二叉搜索树,直接返回false

对左子树和右子树递归进行上述的过程。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private TreeNode preNode;
    public boolean isValidBST(TreeNode root) {
        if (root == null)
            return true;
        //访问左子树
        if (!isValidBST(root.left))
            return false;
        //访问当前节点:如果当前节点小于等于中序遍历的前一个节点直接返回false。
        if (preNode != null && preNode.val >= root.val)
            return false;
        preNode = root;
        //访问右子树
        if (!isValidBST(root.right))
            return false;
        return true;
    }
}