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.

思路一:前序遍历

引用 http://discuss.leetcode.com/questions/47/validate-binary-search-tree

You must understand the difference between Binary Tree and Binary Search Tree (BST). Binary tree is a tree data structure in which each node has at most two child nodes. A binary search tree (BST) is based on binary tree, but with the following additional properties:

  • 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.

This question is a very good interview question, because it really tests your understanding of the definition of BST. Most people will fall to this first trap, and gives the following algorithm:

Assume that the current node's value is k. Then for each node, check if the left node's value is less than k and the right node's value is greater than k. If all of the nodes satisfy this property, then it is a BST.

It sounds correct and convincing, but look at this counter example below: A sample tree which we name it as binary tree (1).

    10
   /  \
  5   15     -------- binary tree (1)
     /  \
    6    20

It's obvious that this is not a valid BST, since (6) could never be on the right of (10).

Based on BST's definition, we can then easily devise a brute-force solution:

Assume that the current node's value is k. Then for each node, check if all nodes of left subtree contain values that are less than k. Also check if all nodes of right subtree contain values that are greater than k. If all of the nodes satisfy this property, then it must be a BST.

Instead of examining all nodes of both subtrees in each pass, we only need to examine two nodes in each pass.

Refer back to the binary tree (1) above. As we traverse down the tree from node (10) to right node(15), we know for sure that the right node's value fall between 10 and +INFINITY. Then, as we traverse further down from node (15) to left node (6), we know for sure that the left node's value fall between 10 and 15. And since (6) does not satisfy the above requirement, we can quickly determine it is not a valid BST. All we need to do is to pass down the low and high limits from node to node! 

 

因为 BST 是二分查找有序的,所以可以用前序遍历来判断是否满足要求。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(!root)
            return true;
        return isValid(root,INT_MIN,INT_MAX);        
    }
    
    bool isValid(TreeNode *root, int min, int max) {
        if(!root)    
            return true; 
        if(min<root->val && root->val<max)
        {
            return isValid(root->left,min,root->val) && isValid(root->right,root->val,max);            
        }
        else 
            return false;   
    }       
};

 

最新 java(目前测试集合过不去了)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public boolean isValidBST(TreeNode root) {

        if(root == null){
            return true;
        } 
        if(root.left == null && root.right == null){
            return true;
        }
        return checkValid(root, Integer.MIN_VALUE, Integer.MAX_VALUE);
        //return checkValid(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }
    
    private boolean checkValid(TreeNode root, int min, int max){
        if(root == null){
            return true;
        }
        // if(root.val == Integer.MIN_VALUE){
        //     return root.left==null && checkValid(root.right, root.val, max);
        // } 
        // if(root.val == Integer.MAX_VALUE){
        //     return root.right==null && checkValid(root.left, min, root.val);
        // }
        if(min < root.val && root.val < max){
            return checkValid(root.left, min, root.val) && checkValid(root.right, root.val, max);
        } else {
            return false;
        }
    }
}


思路二:中序遍历

遍历存储,判断有序

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(!root)  
            return true;  
        vector<int> myvector;  
        midOrder(root,myvector);  
        int len = myvector.size();  
        int i=0;  
        while(i<len-1)  
        {  
            if(myvector[i]>=myvector[i+1])  
                break;  
            i++;  
        }  
        if(i==len-1)
            return true;
        else 
            return false;
    }  
    void midOrder(TreeNode *root, vector<int> &myvector) {  
        if(!root)  
            return ;  
        midOrder(root->left,myvector);  
        myvector.push_back(root->val);  
        midOrder(root->right,myvector);          
    }   
};

 

Another solution is to do an in-order traversal of the binary tree, and verify that the previous value (can be passed into the recursive function as reference) is less than the current value. This works because when you do an in-order traversal on a BST, the elements must be strictly in increasing order. This method also runs in O(N) time and O(1) space.

中序遍历:从左往右递增的顺序

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(!root)
            return true;
        int min = INT_MIN;
        return isValid(root,min);        
    }
    
    bool isValid(TreeNode *root, int &min) {
        if(!root)    
            return true; 
        if(isValid(root->left,min))
        {
            if(min<root->val)
            {
                min = root->val;
                return  isValid(root->right,min);
            }
            else
                return false;                        
        }
        else 
            return false;   
    }       
};


最新java

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    
    private TreeNode pre = null;
    
    public boolean isValidBST(TreeNode root) {
        
        if(root == null){
            return true;
        } 
        // if(root.left == null && root.right == null){
        //     return true;
        // }
        if(!isValidBST(root.left)) {
            return false;
        }
        if(pre != null && pre.val >= root.val) {
            return false;
        }
        pre = root;
        return isValidBST(root.right);
    }
    
}



中序遍历,从右往左递减的顺序

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(!root)
            return true;
        int max = INT_MAX;
        return isValid(root,max);        
    }
    
    bool isValid(TreeNode *root, int &max) {
        if(!root)    
            return true; 
        if(isValid(root->right,max))
        {
            if(root->val<max)
            {
                max = root->val;
                return  isValid(root->left,max);
            }
            else
                return false;                        
        }
        else 
            return false;   
    }       
};


思路三:利用栈的中序遍历

注意退出条件的判断 !mystack.empty() || root!=NULL

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(!root)
            return true;
        stack<TreeNode *> mystack;
        int min = INT_MIN;
        while(!mystack.empty() || root!=NULL)
        {
            while(root)
            {
                mystack.push(root);
                root = root->left;
            }     
            if(!mystack.empty())
            {
                root = mystack.top();
                mystack.pop();
                if(min<root->val)
                {
                    min = root->val;
                    root = root->right;
                }
                else 
                    return false;
            }
        }
        return true;
    }      
};

 

思路三:后序遍历

结果部分错误!!

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(!root)
            return true;
        bool flagleft = isValidBST(root->left);
        bool flagright = isValidBST(root->right);
        if(!flagleft || !flagright)
            return false;
        else
        {
            if(root->left!=NULL && root->left->val>=root->val)
                return false;
            if(root->right!=NULL && root->val>=root->right->val)
                return false;
            return true;            
        }             
    }      
};

直接用上述的代码是不对的,性质和直接的前序遍历一样,无法保证最开始的图例 6<10 的情况。

但是我改进后,可以得到正确的结果。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isValidBST(TreeNode *root) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        if(!root)
            return true;
        int min = INT_MIN;
        int max = INT_MAX;
        return isValid(root,min,max);
    }
    bool isValid(TreeNode *root, int &min, int &max)
    {
          
        if(!root)
            return true;
        int leftmin;
        int leftmax;
        int rightmin;
        int rightmax;
        bool flagleft = isValid(root->left,leftmin,leftmax);
        bool flagright = isValid(root->right,rightmin,rightmax);
        if(!flagleft || !flagright)
            return false;
        if(root->left==NULL)
        {
            leftmin = root->val;
            leftmax = root->val;
        }
        if(root->left!=NULL && root->val<=leftmax)
            return false;    
        if(root->right==NULL)
        {
            rightmin = root->val;
            rightmax = root->val;
        }
        if(root->right!=NULL && root->val>=rightmin)
            return false;
        min = leftmin;
        max = rightmax;     
        return true;
    } 
    
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值