Leetcode P0098"Validate Binary Search Tree" 题解

2020/09/02 Leetcode

博文中会简要介绍Leetcode P0098题目分析及解题思路。

“Validate Binary Search Tree”是一道比较基础的二叉搜索树问题,考察的核心是二叉搜索树的性质,即给定树结点,其值应当小于右子树最小值,大于左子树最大值。

Given a binary tree, determine if it is a valid binary search tree (BST).

Assume a 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.

这道题有两种通用的思路,一种是通过迭代或者递归将二叉搜索树存储下来,然后在O(n)时间内判断;第二种是通过回溯法,即深度优先搜索或者纯递归,根据二叉搜索树的性质,对于某一树结点,其左子树的最大值应当小于其自身的值,而其右子树的最小值应当大于其自身的值,则每次递归返回以这一树结点为根的子树中的最小值和最大值,将两个最值传到上层。

这两种方法实际的时间复杂度是一样的,都是O(n),但是本文主要关注第二种解法。第二种解法有两种不同实现思路,一种是递归地返回最值,在上层判断合法性,更符合纯递归性质;另一种是将当前值往下传,将其作为上下界,然后在下层判断合法性,一旦不合法即返回,更符合深度优先搜索。

回溯法(纯递归)

递归地返回最值,在上层判断合法性。

以下是Java的题解代码实现。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isValidBST(TreeNode root) {
        if (root == null)
            return true;
        
        this.traverse(root);
        
        return this.isValid;
    }
    
    private boolean isValid = true;
    
    private int[] traverse(TreeNode curr) {
        TreeNode left = curr.left, right = curr.right;
        int min = curr.val, max = curr.val;
        if (left == null && right == null)
            return new int[] {min, max};
        
        if (left != null) {
            int []leftInfo = this.traverse(left);
            this.isValid = this.isValid && (curr.val > leftInfo[1]);
            min = Math.min(min, leftInfo[0]);
        }
        if (right != null) {
            int []rightInfo = this.traverse(right);
            this.isValid = this.isValid && (curr.val < rightInfo[0]);
            max = Math.max(max, rightInfo[1]);
        }
        
        return new int[] {min, max};
    }
}

回溯法(深度优先搜索)

将当前值往下传,将其作为上下界,然后在下层判断合法性。

以下是Java的题解代码实现。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isValidBST(TreeNode root) {
        return this.validate(root, null, null);
    }
    
    private boolean validate(TreeNode curr, TreeNode lower, TreeNode upper) {
        if (curr == null)
            return true;
        
        if (lower != null && curr.val <= lower.val)
            return false;
        
        if (upper != null && curr.val >= upper.val)
            return false;
        
        return (this.validate(curr.left, lower, curr) && this.validate(curr.right, curr, upper));
    }
}

以下是C++的题解代码实现。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode* root) {
        return this->Validate(root, NULL, NULL);
    }
    
private:
    bool Validate(TreeNode *curr, TreeNode *lower, TreeNode *upper) {
        if (curr == NULL)
            return true;
        
        TreeNode *left = curr->left, *right = curr->right;
        int val = curr->val;
        if (lower != NULL && val <= lower->val) 
            return false;
        if (upper != NULL && val >= upper->val)
            return false;
        
        return this->Validate(left, lower, curr) && this->Validate(right, curr, upper);
    }
    
};

Search

    Table of Contents