LintCode-95: Validate Binary Search Tree (BST经典题)

  1. 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.
A single node tree is a BST
Example
Example 1:

Input: {-1}
Output:true
Explanation:
For the following binary tree(only one node):
-1
This is a binary search tree.
Example 2:

Input: {2,1,4,#,#,3,5}
Output: true
For the following binary tree:
2
/
1 4
/
3 5
This is a binary search tree.

解法1:
首先要注意的是BST的定义:

  1. root的值要大于所有左子树的节点的值,小于所有右子树节点的值。所以不能单单和左子节点与右子节点比较
    像下面这个代码就不会通过这个测试用例:
    10,5,15,#,#,6,20
    因为该例并非BST (10>6)。
    bool isValidBST(TreeNode * root) {
        if (!root)
            return true;
        
        if (root && !root->left && !root->right) 
            return true;
        
        return isValidBST(root->left) && 
                isValidBST(root->right) && 
               (root->left ? root->val > root->left->val : true) &&
               (root->right ? root->val < root->right->val : true);
    }
  1. helper()函数会返回该root所代表的子树里面的最大值和最小值。左右子树的最大值和最小值都要考虑。
    考虑
  2. min, max 还要考虑root本身的值。
  3. 下面链接有两个version值得好好研究。下次学习。
    https://www.jiuzhang.com/solution/validate-binary-search-tree/#tag-highlight-lang-cpp

另外,这个链接关于LCA的讨论好像很不错,下次参考。
https://www.hrwhisper.me/algorithm-lowest-common-ancestor-of-a-binary-tree/

代码如下:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = 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) {
        if (!root)
            return true;
        
        if (root && !root->left && !root->right) 
            return true;
        
        ReturnType leftRet = helper(root->left);
        ReturnType rightRet = helper(root->right);
        
        return isValidBST(root->left) && 
               isValidBST(root->right) && 
               (root->left ? root->val > leftRet.max : true) &&
               (root->right ? root->val < rightRet.min : true);
    }
    
private:
    struct ReturnType {
        int max;
        int min;
        ReturnType(int a=INT_MIN, int b=INT_MAX) : max(a), min(b) {}
    };
    
    ReturnType helper(TreeNode* root) {
        ReturnType ret;
        
        if (!root) 
            return ret;
        
        if (root && !root->left && !root->right) 
            return ReturnType(root->val, root->val);
            
        ReturnType leftRet = helper(root->left);
        ReturnType rightRet= helper(root->right);
        
        ret.max = max(root->val, max(ret.max, max(leftRet.max, rightRet.max)));
        ret.min = min(root->val, min(ret.min, min(leftRet.min, rightRet.min)));
        
        return ret;
    }
};

这个代码效率好像非常非常低,应该是做了很多无用计算。重新改写了一下,这个代码效率高很多。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = 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) {
        if (!root)
            return true;
        
        if (root && !root->left && !root->right) 
            return true;
        
        ReturnType ret = helper(root, LONG_MIN, LONG_MAX);
        
        if (ret.valid)
            return true;
        else
            return false;
    }
    
private:
    struct ReturnType {
        long min;
        long max;
        bool valid;
        ReturnType(long a=LONG_MIN, long b=LONG_MAX, bool c=true) : min(a), max(b), valid(c) {}
    };
    
    ReturnType helper(TreeNode* root, long min, long max) {
        ReturnType ret;
        
        if (!root) 
            return ret;
        
        ReturnType leftRet = helper(root->left, min, (long)root->val);
        ReturnType rightRet= helper(root->right, (long)root->val, max);
        
        if (!leftRet.valid || !rightRet.valid || root->val <= min || root->val >= max)
            return ReturnType(min, max, false);
        
        return ReturnType(min, max, true);
    }
};

解法3:
在构造一个BST时,一个左节点的值介于父亲子树的最小值和父亲值之间,一个右节点的值介于父亲值和父亲子树的最大值之间,才能继续向下构造。
更新:
每个节点都必须大于其左子树的最大值,小于其右子树的最小值,才算合格。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = 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) {
        return helper(root, LONG_MIN, LONG_MAX);
    }
    
private:
    bool helper(TreeNode * root, long leftMax, long rightMin) {
        if (!root) return true;
        if (root->val <= leftMax|| root->val >= rightMin) return false;
        return helper(root->left, leftMax, root->val) && helper(root->right, root->val, rightMin);
        
    }
};

解法4:利用BST的InOrder遍历是递增序列这个特性。


class Solution {
public:
    /**
     * @param root: The root of binary tree.
     * @return: True if the binary tree is BST, or false
     */
    bool isValidBST(TreeNode * root) {
        if (!root) return true;
        inOrderTraversal(root);
        int len = inOrderRes.size();
        for (int i = 1; i < len; i++) {
            if (inOrderRes[i] <= inOrderRes[i - 1]) return false;
        }
        return true;        
    }
private:
    vector<int> inOrderRes;
    void inOrderTraversal(TreeNode *root) {
        if (!root) return;
        inOrderTraversal(root->left);
        inOrderRes.push_back(root->val);
        inOrderTraversal(root->right);
    }
};

代码同步在
https://github.com/luqian2017/Algorithm/

非递归的版本如下:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = 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) {
        stack<TreeNode *> stk;
        TreeNode *pre = nullptr;
        while (!stk.empty() || root) {
            while(root) {
                stk.push(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            if (pre && pre->val >= root->val) return false;
            pre = root;
            root = root->right;
        }
        return true;
    }
};

5刷:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

struct ResultType {
    bool isValid;
    long long maxVal;
    long long minVal;
    ResultType(bool isV, long long maxV, long long minV) : isValid(isV), maxVal(maxV), minVal(minV) {}
};

class Solution {
public:
    /**
     * @param root: The root of binary tree.
     * @return: True if the binary tree is BST, or false
     */
    bool isValidBST(TreeNode * root) {
        return helper(root).isValid;
    }
private:
    ResultType helper(TreeNode *root) {
        if (!root) {
            return ResultType(true, LLONG_MIN, LLONG_MAX);//注意不能用INT_MIN和INT_MAX,不然如果节点值就是INT_MIN或INT_MAX会出错。
        }
        if (!root->left && !root->right) {
            return ResultType(true, root->val, root->val);
        }
        ResultType left = helper(root->left);
        if (!left.isValid) {
            return ResultType(false, 0, 0);
        }
        ResultType right = helper(root->right);
        if (!right.isValid) {
            return ResultType(false, 0, 0);
        }
        if (root->val > left.maxVal && root->val < right.minVal) {
            return ResultType(true, root->right ? right.maxVal : root->val, root->left ? left.minVal : root->val);
        } //注意这里要加判断root->right和root->left是否存在的情况,不然的话,如果不存在,那么right.maxVal和left.minVal会用到LLONG_MIN和LLONG_MAX
        return ResultType(false, 0, 0);
    }    
};

6刷:

/**
 * 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 helper(root, NULL, NULL);
    }
private:
    bool helper(TreeNode *root, TreeNode *minNode, TreeNode *maxNode) {
        if (!root) return true;
        if (minNode) {
            if (minNode->val >= root->val) return false;
        }
        if (maxNode) {
            if (maxNode->val <= root->val) return false;
        }
            
        return helper(root->left, minNode, root) && helper(root->right, root, maxNode);
    }
};

8刷:

/**
 * 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) {
        if (!root) return true;
        TreeNode *visited = new TreeNode(-1);
        long long preV = (long long)INT_MIN - 1;
        goLeft(root);        
        while (!stk.empty()) {
            TreeNode *topNode = stk.top();
            if ((!topNode->left || topNode->left == visited) && topNode->right != visited) {
                //inorder code here
                if ((long long)topNode->val <= preV) return false;
                preV = (long long)topNode->val;
                goLeft(topNode->right);
            }
            if (!topNode->right || topNode->right == visited) {
                //postorder code here
                visited = topNode;
                stk.pop();
            }
         }
         return true;
    }
private:
    stack<TreeNode *> stk;
    void goLeft(TreeNode *root) {
        while (root) {
            //preorder code here
            stk.push(root);
            root = root->left;
        }
        return;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值