题目:验证二叉搜索树

解法一:通过中序遍历将整棵树装入vector,再判断数组是否单调

具体实现非常简单,但不是一个好方法,因为他需要先将所有节点的数值装入容器,再进行比较,然而实际上每次比较只需要使用到两个节点,这会造成空间的浪费

所以应该使用“边遍历,边比较”的方法

 1void traversal(TreeNode* root, std::vector<int>& v)
 2{
 3    if(!root) return;
 4
 5    traversal(root->left, v);
 6
 7    v.push_back(root->val);
 8
 9    traversal(root->right, v);
10}
11
12bool isValidBST(TreeNode* root)
13{
14    std::vector<int> vec;
15    traversal(root, vec);
16
17    int sz = vec.size();
18    for(int i = 0; i < sz - 1; i++)
19    {
20        if(vec[i+1] <= vec[i]) return false;
21    }
22    return true;
23}

解法二:使用指针成员装载当前节点的父节点,并在访问当前节点时就继续比较

这样就避免了在堆上分配内存,所有操作都只在栈上进行

相较于上一个方法,这个方法的空间复杂度从O(n)下降到了O(h),其中h为树的最大深度

 1class Solution
 2{
 3public:
 4    bool isValidBST(TreeNode* root)
 5    {
 6        if(!root) return true;                         // 遍历到叶子节点之后进行剪枝,返回上一个节点
 7        if(!isValidBST(root->left)) return false;      // 如果左子树底下的节点已经不满足规则,就没必要继续遍历了
 8        if(prev && root->val <= prev->val) return false;
 9        prev = root;
10        return isValidBST(root->right);                // 此时左边已经全部满足规则,只需要判断右子树是否也全部满足规则即可
11    }
12private :
13    TreeNode* prev = nullptr;
14};

补充解法:递归维护上下界

 1bool isValid(TreeNode* root, long min_val, long max_val)
 2{
 3    if(root == nullptr) return true;
 4    if(root->val <= min_val || max_val <= root->val) return false;
 5    return isValid(root->left, min_val, root->val) &&
 6           isValid(root->right, root->val, max_val);
 7}
 8bool isValidBST(TreeNode* root)
 9{
10    return isValid(root, LONG_MIN, LONG_MAX);
11}

来源:语雀原笔记