【LeetCode】Validate Binary Search Tree 验证二叉查找树 - Medium+

93 篇文章 0 订阅
69 篇文章 0 订阅

验证二叉查找树
给定一个二叉树,判断它是否是合法的二叉查找树(BST)

一棵BST定义为:

节点的左子树中的值要严格小于该节点的值。
节点的右子树中的值要严格大于该节点的值。
左右子树也必须是二叉查找树。
一个节点的树也是二叉查找树。

样例
一个例子:

  2
 / \
1   4
   / \
  3   5
上述这棵二叉树序列化为 {2,1,4,#,#,3,5}.

标签
分治法 二叉树 递归 二叉查找树

这里写图片描述

【分析】
SOLUTION 1:
使用Iterator 中序遍历的方法,判断整个数列是否保持增序即可。

算法思想:

http://www.cnblogs.com/shuaiwhu/archive/2011/04/20/2065055.html

  1. 采用栈的话,先寻找最左边的节点,把经过的节点都存入栈中,第一个被弹出来的为最左节点,那么访问其右子树,对右子树也像前面一样遍历,整个流程跟递归一样。
public boolean isValidBST1(TreeNode root) {
        // Just use the inOrder traversal to solve the problem.
        if (root == null) {
            return true;
        }

        Stack<TreeNode> s = new Stack<TreeNode>();
        TreeNode cur = root;

        TreeNode pre = null;

        while(true) {
            // Push all the left node into the stack.
            while (cur != null) {
                s.push(cur);
                cur = cur.left;
            }

            if (s.isEmpty()) {
                break;
            }

            // No left node, just deal with the current node.
            cur = s.pop();

            if (pre != null && pre.val >= cur.val) {
                return false;
            }

            pre = cur;

            // Go to the right node.
            cur = cur.right;
        }

        return true;
    }

2.不采用栈的话,先是访问最左节点,然后访问其右子树,然后回溯到最左节点的父节点,不断重复这个过程,思路还是一样。这里参考了重剑无锋的http://blog.csdn.net/kofsky/archive/2008/09/05/2886453.aspx

3.引自大神的思想:http://blog.csdn.net/fightforyourdream/article/details/14444883

我们可以设置上下bound,递归左右子树时,为它们设置最大值,最小值,并且不可以超过。

注意:下一层递归时,需要把本层的up 或是down继续传递下去。相当巧妙的算法。

/*
        SOLUTION 2: Use the recursive version.
        REF: http://blog.csdn.net/fightforyourdream/article/details/14444883
    */
    public boolean isValidBST2(TreeNode root) {
        // Just use the inOrder traversal to solve the problem.
        if (root == null) {
            return true;
        }

        return dfs(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    public boolean dfs(TreeNode root, long low, long up) {
        if (root == null) {
            return true;
        }

        if (root.val >= up || root.val <= low) {
            return false;
        }

        return dfs(root.left, low, root.val) 
           && dfs(root.right, root.val, up);
    }

Solution 3:
使用一个全局变量,用递归的中序遍历来做,也很简单(但全局变量主页君不推荐!)

/*
        SOLUTION 3: Use the recursive version3.
    */
    TreeNode pre = null;

    public boolean isValidBST(TreeNode root) {
        // Just use the inOrder traversal to solve the problem.
        return dfs4(root);
    }

    public boolean dfs4(TreeNode root) {
        if (root == null) {
            return true;
        }

        // Judge the left tree.
        if (!dfs4(root.left)) {
            return false;
        }

        // judge the sequence.
        if (pre != null && root.val <= pre.val) {
            return false;
        }
        pre = root;

        // Judge the right tree.
        if (!dfs4(root.right)) {
            return false;
        }

        return true;
    }

(4)Java
SOLUTION 4:
同样是递归,但是把左右子树的min, max值返回,与当前的root值相比较。比较直观。

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
class ResultType{
    boolean is_bst;
    int maxValue, minValue;

    public ResultType(boolean is_bst, int maxValue, int minValue) {
    this.is_bst = is_bst;
    this.maxValue = maxValue;
    this.minValue = minValue;
     }
}

public class Solution {
    /*
     * @param root: The root of binary tree.
     * @return: True if the binary tree is BST, or false
     */

    private ResultType ValidateBstHelper(TreeNode root){
        if(root == null){
            return new ResultType(true, Integer.MIN_VALUE, Integer.MAX_VALUE);
            //当前节点无效,传入false。
            //Trick: 而传入整型的最大/小值是为了避免影响最后Math.max/min()的判断
        }
        ResultType left = ValidateBstHelper(root.left);
        ResultType right = ValidateBstHelper(root.right);

        // if(root.left == null || root.right == null){
        if(!left.is_bst || !right.is_bst){
            return new ResultType(false, 0, 0);
            //以当前节点为根的子bst是无效的。故传入false,但他本身节点非空,说明确实存在该节点,故后面传入0(因为无用)
                        // if is_bst is false then minValue and maxValue are useless

        }

        if(root.left != null && left.maxValue >= root.val ||
            root.right != null && right.minValue <= root.val){//正常的bst应满足max(左子树)<root<min(右子树)。此处列举不合法的bst。
            return new ResultType(false, 0, 0);
        }

        return new ResultType(true, Math.max(root.val, right.maxValue), Math.min(root.val, left.minValue) );//以便回调
    }
    public boolean isValidBST(TreeNode root) {

        ResultType r = ValidateBstHelper(root);
        return r.is_bst;
    }
}

(2)C++

// version 1: traverse
class Solution {
private:
    TreeNode *lastNode = NULL;
public:
    /**
     * @param root: The root of binary tree.
     * @return: True if the binary tree is BST, or false
     */
    bool isValidBST(TreeNode *root) {
        if (root == NULL) {
            return true;
        }
        if (!isValidBST(root->left)) {
            return false;
        }
        if (lastNode != NULL && lastNode->val >= root->val) {
            return false;
        }
        lastNode = root;
        return isValidBST(root->right);
    }
};

// traverse 2: divide & conquer
class ResultType {
public:
    bool isBST;
    TreeNode *maxNode, *minNode;
    ResultType() {
        this->isBST = true;
        this->maxNode = NULL;
        this->minNode = NULL;
    }
};

class Solution {
public:
    /**
     * @param root: The root of binary tree.
     * @return: True if the binary tree is BST, or false
     */
    bool isValidBST(TreeNode *root) {
        ResultType result = helper(root);
        return result.isBST;
    }

    ResultType helper(TreeNode *root) {
        ResultType result;
        if (root == NULL) {
            return result;
        }

        ResultType left = helper(root->left);
        ResultType right = helper(root->right);

        if (!left.isBST || !right.isBST) {
            result.isBST = false;
            return result;
        }

        if (left.maxNode != NULL && left.maxNode->val >= root->val) {
            result.isBST = false;
            return result;
        }

        if (right.minNode != NULL && right.minNode->val <= root->val) {
            result.isBST = false;
            return result;
        }

        result.isBST = true;
        result.minNode = left.minNode == NULL ? root : left.minNode;
        result.maxNode = right.maxNode == NULL ? root : right.maxNode;
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值