zoukankan      html  css  js  c++  java
  • [LeetCode] 98. Validate Binary Search Tree 验证二叉搜索树

    验证二叉搜索树

    CategoryDifficultyLikesDislikes
    algorithms Medium (31.28%) 620 -

    TagsCompanies

    给定一个二叉树,判断其是否是一个有效的二叉搜索树。

    假设一个二叉搜索树具有如下特征:

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

    示例 1:

    输入:
        2
       / 
      1   3
    输出: true

     

    示例 2:

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

    输入一个树,判断该树是否是合法的二分查找树(二叉搜索树),95题做过生成二分查找树。二分查找树定义如下:

    1. 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
    2. 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
    3. 任意节点的左、右子树也分别为二叉查找树;
    4. 没有键值相等的节点。

    解法一

        开始的时候以为可以很简单的用递归写出来。想法是,左子树是合法二分查找树,右子树是合法二分查找树,并且根节点大于左孩子,小于右孩子,那么当前树就是合法二分查找树。

    当然,这个解法没有通过。对于下面的测试用例,这种解法是错误的。

      10

         /

       5 15
         /
        6 20

       虽然满足左子树是合法二分查找树,右子树是合法二分查找树,并且根节点大于左孩子,小于右孩子,但这个树不是合法的二分查找树。因为右子树中的 6 小于当前根节点 10。

       所以我们不应该判断「根节点大于左孩子,小于右孩子」,而是判断「根节点大于左子树中最大的数,小于右子树中最小的数」。

       正确代码如下:

       

     1 class Solution {
     2 public:
     3     bool isValidBST(TreeNode* root)//二叉树的中序遍历
     4     {  
     5          //递归出口
     6         if(!root) return true;
     7         //搜索二叉树中根结点应小于左子树的最右边节点(左子树最大值),大于右子树的最左边节点(右子树最小值)
     8         bool root_valid = false;
     9         TreeNode* most_left_ptr = root->left; //左子树的最右节点(左子树最大值)
    10         TreeNode* most_right_ptr = root->right; //右子树的最左节点(右子树最小值)
    11         //走到最右求左子树最大值
    12         TreeNode* workPtr = most_left_ptr;
    13         while(workPtr)
    14         {
    15             most_left_ptr = workPtr;
    16             workPtr = workPtr->right;
    17         }
    18         //走到最左求右子树最小值
    19         workPtr = most_right_ptr;
    20         while(workPtr)
    21         {
    22             most_right_ptr = workPtr;
    23             workPtr = workPtr->left;
    24         }
    25 
    26         if(most_left_ptr&&most_right_ptr)//左右子树都非空
    27         {
    28             root_valid = root->val>most_left_ptr->val&&root->val<most_right_ptr->val;
    29         }
    30         else if(most_left_ptr)//左非空、右空
    31         {
    32             root_valid = root->val>most_left_ptr->val;
    33         }
    34         else if(most_right_ptr)//左空,右非空
    35         {
    36             root_valid = root->val<most_right_ptr->val;
    37         }
    38         else//当前根节点是叶子节点
    39         {
    40             root_valid = true;
    41         }
    42        //递归地对左右子树做同样的判断
    43         bool left_valid = isValidBST(root->left);
    44         bool right_valid = isValidBST(root->right);
    45         
    46         return root_valid&&left_valid&&right_valid;
    47     }
    48 };

     解法二:

        解法一中,我们是判断根节点是否合法,找到了左子树中最大的数,右子树中最小的数。 由左子树和右子树决定当前根节点是否合法。

    但如果正常的来讲,明明先有的根节点,按理说根节点是任何数都行,而不是由左子树和右子树限定。相反,根节点反而决定了左孩子和右孩子

    的合法取值范围。所以,我们可以从根节点进行 DFS,然后计算每个节点应该的取值范围,如果当前节点不符合就返回 false。

    代码如下:

    class Solution {
    public:
        bool isValidBST(TreeNode* root)//二叉树的中序遍历
        {  
            //最小、最大整数取 INT_MIN 和 INT_MAX会有测试用例通不过
             long int low = LONG_MIN;
             long int high = LONG_MAX;
             return helper(root,low, high);
        }
        bool helper(TreeNode* root,long int low, long int high)
        {
            if(!root) return true;
            int value  = root->val;
            if(value<=low || value>=high) return false;
            bool left_valid = helper(root->left,low,value);
            bool right_valid = helper(root->right,value,high);
            return left_valid&&right_valid;
        }
    };
  • 相关阅读:
    对象
    语句
    表达式和运算符
    类型、值和变量
    词法结构
    javac命令详解(下)
    javac命令详解(上)
    jar 查找多jar包中类的办法
    find -exec
    java编译相关问题总结
  • 原文地址:https://www.cnblogs.com/wangxf2019/p/13138737.html
Copyright © 2011-2022 走看看