day39_0098.验证二叉搜索树

0098.验证二叉搜索树

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        if (root == NULL)   return false;
        if (root->left) {
            if (root->left->val > root->val)
                return false;
            else
                return isValidBST(root->left);
        }
        if (root->right) {
            if (root->right->val < root->val)
                return false;
            else
                return isValidBST(root->right);
        }
        return true;
    }
};
  • 以上是我的迭代法 有问题
  • 下面总结卡哥的几种代码
    • 递归法1----借助数组比较大小
    • 递归法2-----初始化最小值为LONG_MIN
    • 递归法3----直接将整棵树最左边的叶子节点设为最小值
    • 迭代法
  • 递归法1
class Solution {
private:
    vector<int> vec;
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); 
        traversal(root->right);
    }
public:
    bool isValidBST(TreeNode* root) {
        vec.clear(); 
        traversal(root);
        for (int i = 1; i < vec.size(); i++) {
            if (vec[i] <= vec[i - 1]) return false;
        }
        return true;
    }
};
  • 思路解析

    • 把数组定义和traversal函数放在private里

    • root == NULL 返回真而不是假

      • 理由是 可以使用反证法 如果此时结点为NULL 那么你希望返回假结束所有遍历吗 当然不能 只有元素大小关系不符合左小于中小于右的时候 才需要return false

      • 关于空值有必要再次强调 假设root == NULL 可以把空值当作参数进行传递如traversal(root); 但不能对空值进行任何操作如(root->left);

    • 关于遍历函数

      • 采用什么遍历方式取决于遍历的目的: 把所有节点元素值按照左中右的顺序存入数组vec中 以便在主函数中通过判断数组是否为有序递增来验证遍历得到的树是否为二叉搜索树 因此遍历函数traversal采用中序遍历
      • 遍历的写法: 中序遍历:遍历左----对当前节点(中间节点)的操作--------遍历右
    • 关于主函数

      • 注意二叉搜索树 元素值相等也是不被允许的一种情况
  • 递归法2-----初始化最小值为LONG_MIN

class Solution {
public:
    long long maxVal = LONG_MIN;
    bool isValidBST(TreeNode* root) {
        if (root == NULL)   return true;

        bool left = isValidBST(root->left);  // 左
        if (maxVal < root->val)  // 中
            maxVal = root->val;
        else
            return false;
        bool right = isValidBST(root->right);  //  右

        return left && right;
    }
};
  • 思路解析

    • maxVa之所以选择longlong类型最小值 是因为后台数据有int最小值测试用例

    • 如果测试数据中有 longlong的最小值, 不可能在初始化一个更小的值 建议避免 初始化最小值,如下代码方法取到最左面节点的数值来比较。

  • 递归法3----直接将整棵树最左边的叶子节点设为最小值

class Solution {
public:
    TreeNode* pre = NULL;
    bool isValidBST(TreeNode* root) {
        if (root == NULL)  return true;

        bool left = isValidBST(root->left);
        if (pre != NULL && pre->val >= root->val)
            return false;
        pre = root;
        bool right = isValidBST(root->right);

        return left && right;
    }
};
  • 思路解析

    • 既然不单独再写一个遍历函数而是直接在所给的主函数里面进行遍历 那么必然有些元素需要额外定义在主函数外 如这段代码的pre和上一段代码的maxVal变量
    • 这段代码逻辑是 在中序遍历的框架下 先获取到整棵树最左边元素值
  • 迭代法

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* pre = NULL; // 记录前一个节点
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) {
                st.push(cur);
                cur = cur->left;                // 左
            } else {
                cur = st.top();                 // 中
                st.pop();
                if (pre != NULL && cur->val <= pre->val)
                return false;
                pre = cur; //保存前一个访问的结点

                cur = cur->right;               // 右
            }
        }
        return true;
    }
};
  • 下次看
posted @ 2022-12-22 20:27  跬步瑶  阅读(30)  评论(0)    收藏  举报