98. 验证二叉搜索树--初级算法

链接:98. 验证二叉搜索树 - 力扣(LeetCode)

题目描述

        给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。有效 二叉搜索树定义如下:

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

示例 1:

输入:root = [2,1,3]
输出:true

示例 2:

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

解题思路

一、递归

        考虑到有效二叉搜索树要保证左右子树也是二叉搜索树,所以可以用递归函数判断。其中要确保左孩子节点值小于父母节点值,右孩子节点的值大于父母节点的值,所以需要每次传入较大和较小的值。注意初始时,两个参数分别为最大最小值,当递归左子树时,当前节点的值作为较大值upper传入参数,当递归右子树时当前节点的值作为较小值lower传递参数。

代码实现
/**
 * 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) {
        //调用函数方便实现判断,其中LONG_MIN,LONG_MAX为long类型的最小最大关键字
        return helper(root,LONG_MIN,LONG_MAX);
    }
    bool helper(TreeNode* root,long long lower,long long upper){
        if(!root){
            return true;
        }
        //当前节点的值比较小值小或者比较大值大则说明不是二叉搜索树
        //第一次递归,lower为long类型的最小值,upper为long类型的最大值
        //之后二者就为当前值的较大值和较小值
        if(root->val <= lower || root->val >= upper){
            return false;
        }
        //向左递归,则当前值为左子树的较大值;向右递归,则当前值为右子树的较小值
        return helper(root->left,lower,root->val) && helper(root->right,root->val,upper);
    }
};

二、中序遍历

        利用对二叉搜索树的中序遍历结果为升序排列的特点,可以一边遍历一边与上一个节点的值进行比较,一旦出现当前节点值不大于上一节点值,则直接返回false,若全部遍历结束则返回true。

代码实现
/**
 * 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;
        }
        stack<TreeNode*> st;//存储节点
        long long last_val = (long long )INT_MIN-1;//long long类型最小值
        while(!st.empty()||root!=nullptr){
            //一直往左深入遍历
            while(root){             
                st.push(root);
                root=root->left;
            }
            //左子树入栈完毕开始判断
            root=st.top();
            st.pop();
            //出现不符合条件的节点则直接返回
            if(root->val <= last_val){
                return false;
            }
            //存储当前值,作为下一个节点的前一个节点值
            last_val=root->val;
            //遍历右子树
            root = root->right;
        }

        return true;
    }
    
};

总结

  • 前序遍历 在某些数据下不需要递归到边界(base case)就能返回,而中序遍历和后序遍历至少要递归到一个边界,从这个角度上来说,前序遍历是最快的。
  • 中序遍历 很好地利用了二叉搜索树的性质,使用到的变量最少。
  • 后序遍历 的思想是最通用的,即自底向上计算子问题的过程。与动态规划思想类似。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值