104、【树与二叉树】leetcode ——98. 验证二叉搜索树:递归法[先序+中序+后序]+迭代法(C++版本)

news2024/11/24 14:44:01

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原题链接:98. 验证二叉搜索树

解题思路

BST的特点是:当前结点的值,比左子树中的全部结点都大,比右子树中全部结点都小。在代码实现中,要注意不要对比的是某一结点和某一侧的全部值之间的关系,不能只有结点与结点间的关系对比,否则容易出现非法BST。

一、递归法

根据BST的特征,

(1)中序遍历

根据BST的特点,当对BST进行中序遍历时,结点的值应呈单调递增的形式。

1)辅助vector
根据单调性,我们可以在遍历时,用vector记录结点值,然后再顺序遍历vector中的值,当以单调形式递增时,返回true,否则返回false

/**
 * 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:
    vector<int> path;
    // 按中序遍历,左中右的顺序,将root中元素存入path中
    void traversal(TreeNode* root) {
        if(!root)       return ;
        traversal(root->left);
        path.push_back(root->val);
        traversal(root->right);
    }
    bool isValidBST(TreeNode* root) {
        traversal(root);
        // 若为BST,则path中元素应该单调递增
        for(int i = 0; i < path.size() - 1; i++) {
            if(path[i] >= path[i + 1])       return false;
        }
        return true;
    }
};

2)记录上一个结点的值
设置maxValue,记录上一个遍历元素的值,若为BST,则当前的值,应大于上一个遍历的值。

/**
 * 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:
    // 因为测试数据中有INT_MIN和INT_MAX,所以用long long
    long long maxValue = LONG_MIN;
    bool isValidBST(TreeNode* root) {
        if(!root)       return true;
        bool left = isValidBST(root->left);
        // 中序遍历,验证元素是否从小到大递增
        if(maxValue < root->val)    maxValue = root->val;
        else            return false;
        bool right = isValidBST(root->right);
        return left && right;
    }
};

3)双指针法
为防止测试数据有LONG_MIN,因此采用记录前后元素,双指针对比数据大小的方式。

/**
 * 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:
    // 设置一个指针指向前一个遍历元素
    TreeNode* pre = NULL;
    bool isValidBST(TreeNode* root) {
        if(!root)       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;
    }
};

(2)先序遍历

BST要保证,当前节点全部大于左子树中的结点,全部小于右子树中的结点。

在向左子树遍历时,只会遇到两种情况:
(1)向左子树的左子树结点遍历;(2)向右子树的左子树结点遍历。
对于第一种情况,左子树的左子树结点,只要其左结点比当前结点小即可。对于第二种情况,不仅要求左结点要比当前结点小,还要保证不能小过之前的右子树的根结点及其以上的值

在向右子树遍历时,同理也会遇到两种情况:
(1)向右子树的右子树结点遍历;(2)向左子树的右子树结点遍历。
对于第一种情况,右子树的右子树结点,只要其右结点比当前节点大即可。对于第二种情况,不仅要求右结点比当前结点大,还要保证不能大过之前的左子树的根结点及其以上的值。

因此,我们需要设置两个局部变量,maxleft记录当前结点的左子树不可超过的值,minright当前结点右子树中的结点不可小于的值。当遍历到左子树结点时,更新maxleft(向左应更小,因此取较小值)。当遍历到右子树结点时,更新minright(向右更大,因此取较大值)。

/**
 * 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 res = true;
    // root:当前遍历结点、maxleft:规定左子树结点不能超过的值,minright:规定右子树中结点不能小于的值
    void traversal(TreeNode* root, long long maxleft, long long minright) {
        if(!root->left && !root->right)             return ;
        // 处理左的左和右的左
        if(root->left) {
            long long left = root->left->val;
            // 当左子树的值小于当前结点的值,若还处于右子树时,该结点的值比右子树中不能小于的值大,则继续遍历
            if(left < root->val && left > minright) {                
                // 向左子树遍历时,更新左子树结点不能超过的值,取较小值
                // long long l = root->val < maxleft ? root->val : maxleft;		
                // 这里可以不用再比较,因为当向左遍历之前成立时,说明当前结点一定小于之前的根节点
                traversal(root->left, root->val, minright);
            } else {
                res = false;
                return ;
            }            
        }
        // 处理右的右和左的右
        if(root->right) {
            long long right = root->right->val;
            // 当右子树的值大于当前结点的值,若还处于左子树时,该结点的值比左子树中不能超过的值小,则继续遍历
            if(right > root->val && right < maxleft) {
                // 向右子树遍历时,更新右子树不能小于的值,取较大值
                // long long r = root->val > minright ? root->val : minright;		
                // 这里可以不用再比较,因为当向右遍历之前成立时,说明当前结点一定大于之前的根节点
                traversal(root->right, maxleft, root->val);
            } else {
                res = false;
                return ;
            }
        }

    }
    bool isValidBST(TreeNode* root) {
        // 测试数据中有关INT_MAX和INT_MIN,因此用long long
        traversal(root, LONG_MAX, LONG_MIN);
        return res;
    }
};

(3)后序遍历

image.png

class Solution {
public:
    bool helper(TreeNode* root, long long lower, long long upper) {
        if (root == nullptr) {
            return true;
        }
        if (root -> val <= lower || root -> val >= upper) {
            return false;
        }
        return helper(root -> left, lower, root -> val) && helper(root -> right, root -> val, upper);
    }
    bool isValidBST(TreeNode* root) {
        return helper(root, LONG_MIN, LONG_MAX);
    }
};

时间复杂度 O ( n ) O(n) O(n)
空间复杂度 O ( n ) O(n) O(n)

二、迭代法

/**
 * 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) {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* pre = NULL;
        while(cur || !st.empty()) {
            while(cur) {
                st.push(cur);
                cur = cur->left;
            }
            cur = st.top();      st.pop();
            if(pre != NULL && cur->val <= pre-<val)
                return false;
            pre = cur;
            cur = cur->right;            
        }
    }
};

参考文章:98.验证二叉搜索树、验证二叉搜索树

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【论文阅读】CenterNet

论文题目&#xff1a;Objects as Points&#xff08;CVPR2019&#xff09; 论文地址&#xff1a;https://arxiv.org/pdf/1904.07850.pdf 发布时间&#xff1a;2019.4.16 机构&#xff1a;UT Austin&#xff0c;UC Berkeley 代码&#xff1a;https://github.com/xingyizhou/…

小程序事件基础

小程序事件--基础小程序事件事件简介小程序事件—事件传参事件对象属性target和currentTarget事件对象属性获取和设置data数据获取&设置data获取和设置data数据—进阶小程序的渲染层与逻辑层小程序事件 事件简介 事件是视图层到逻辑层的通讯方式。负责将用户对于的页面的操…

云上的米开朗基罗:在不确定时代,寻找建筑般的确定性

文艺复兴三杰之一的米开朗基罗&#xff0c;被称为“天才建筑师”。其实他一生留下的建筑并不多&#xff0c;仅仅有美第奇礼拜堂、卡比多广场、圣彼得大教堂穹顶等寥寥几座。但米开朗基罗却凭借对建筑层次与结构的精妙把握&#xff0c;影响了此后数百年的建筑风格。很多人认为&a…

【代码随想录】动态规划:关于01背包问题,你该了解这些!(滚动数组)

01 背包 有n件物品和一个最多能背重量为w的背包 第i件物品的重量是weight[i]&#xff0c; 得到的价值是value[i] &#xff0c; 每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 每一件物品其实只有两个状态&#xff0c;取或者不取&#xff0c;所以…

win下编译opencv+libjpeg-turbo

文章目录前言编译环境下载opencv和jpeg-turbo源码编译jpeg-turbo编译opencv失败&#xff1f;那就直接调用jpeg-turbo库进行编解码前言 opencv默认自带第三方jpeg编解码库&#xff0c;但其性能一般&#xff0c;对高性能需求的程序来说是不适合的&#xff0c;因此我们可以把jpeg…

设计模式学习(八):Proxy代理模式

一、什么是Proxy模式 Proxy是“代理人”的意思&#xff0c;它指的是代替别人进行工作的人。当不一定需要本人亲自进行工作时&#xff0c;就可以寻找代理人去完成工作。但代理人毕竟只是代理人&#xff0c;能代替本人做的事情终究是有限的。因此&#xff0c;当代理人遇到无法自己…

文件上传oss,并查询上传进度(SpringBoot+Redis+Oss+Swagger3)

文章目录诉求技术选型pom配置项目结构文件树图示结构代码实现配置相关配置文件yamlSwagger3配置跨域问题配置oss相关ServiceControllerApplicationSwagger接口操作获取上传文件标识号获取文件上传进度小结诉求 将文件上传到oss&#xff0c;并实时监听上传进度&#xff0c;并将进…

【javaSE】中基本类型和引用类型对象的比较及PriorityQueue中的比较方法

写博客是为了提升自己&#xff0c;也是为了展现自己的学习成果&#xff0c;坚持!坚持!坚持&#xff01;未来是什么样的&#xff0c;闯一闯就知道啦。喜欢就留个关注吧&#xff01;&#xff01;! 目录 一、java对象的比较 1.1java中基本类型的比较 1.2引用对象的比较 1.3引用…

使用云端的GPU进行yolov5的训练

前言本文介绍了使用云端GPU进行yolov5训练环境配置的过程一、创建实例这里使用的是恒源云的GPU服务器&#xff0c;官方网址为恒源云_GPUSHARE-恒源智享云他的用户文档为Tmux - 恒源云用户文档一般的问题在用户文档中都可以找到解决办法。注册并登录后的界面如下图所示。点击云市…

c++11 标准模板(STL)(std::forward_list)(十)

定义于头文件 <forward_list> template< class T, class Allocator std::allocator<T> > class forward_list;(1)(C11 起)namespace pmr { template <class T> using forward_list std::forward_list<T, std::pmr::polymorphic_…

UPerNet:Unified Perceptual Parsing for Scene Understanding论文解读

Unified Perceptual Parsing for Scene Understanding 论文&#xff1a;[1807.10221] Unified Perceptual Parsing for Scene Understanding (arxiv.org) 代码&#xff1a;CSAILVision/unifiedparsing: Codebase and pretrained models for ECCV’18 Unified Perceptual Parsi…

第二章.线性回归以及非线性回归—岭回归

第二章.线性回归以及非线性回归 2.12 岭回归&#xff08;Ridge Regression&#xff09; 1.前期导入&#xff1a; 1).标准方程法[w(XTX)-1XTy]存在的缺陷&#xff1a; 如果数据的特征比样本点还多&#xff0c;数据特征n&#xff0c;样本个数m&#xff0c;如如果n>m&#xf…

5种气血不足的面相

我们常用“气色好”形容人良好的健康状态&#xff0c;反之&#xff0c;气血不足就是不健康的表现。想知道自己是否气血不足&#xff0c;可以从以下几种表现中判断。眼白黄&#xff1a;所谓人老珠黄&#xff0c;就是指眼白的颜色变得浑浊、发黄、有血丝&#xff0c;很可能气血不…

网络编程基础(1)

1 OSI七层模型&#xff08;理论&#xff09; 七层模型&#xff0c;亦称OSI&#xff08;Open System Interconnection&#xff09;。参考模型是国际标准化组织&#xff08;ISO&#xff09;制定的一个用于计算机或通信系统间互联的标准体系&#xff0c;一般称为OSI参考模型或七层…

cycle_gan使用教程

junyanz/pytorch-CycleGAN-and-pix2pix: Image-to-Image Translation in PyTorch (github.com) 如果是用cycle_gan 数据集 /数据集文件夹名&#xff0c;下面四个子文件名 testA testB trainA trainB trainA是A风格图片&#xff0c;trainB是B风格图片。 训练参数 test…

CCF BDCI | 算能赛题决赛选手说明论文-04

基于TPU平台实现人群密度估计 队名&#xff1a;innovation 陈照照 数据科学与大数据技术20级 台州学院 中国-瑞安 479253198qq.com董昊数据科学与大数据技术20级 台州学院 中国-杭州 donghaowifi163.com陈晓聪数据科学与大数据技术20级 台州学院 中国-宁波 2637491…

Golang -- openwechat微信发送消息、自动回复

开篇 马上就要到农历新年了&#xff0c;不妨写一段代码准时为好友们送上祝福。 该 Demo 使用开源项目 openwechat &#xff0c;实现获取好友列表、为好友发送消息、图片或文件&#xff0c;接收来自好友或群组的消息并设置自动回复等功能。 openwechat Github地址 openwechat 文…

管道(匿名,有名)

文章目录Linux 进程间通信的方式管道匿名管道有名管道Linux 进程间通信的方式 管道 管道特点 管道其实是一个在内核内存中维护的缓冲器&#xff0c;这个缓冲器的存储能力是有限的&#xff0c;不同的操作系统大小不一定相同管道拥有文件的特质&#xff1a;读操作、写操作 匿名管…

线扫相机DALSA-变行高拍照

CamExpert在线阵模式中默认的Buffer设置是Fixed Length。在这种设置下&#xff0c;在一帧采集结束前所接收到的新的帧触发信号都会被忽略。在有的应用中&#xff0c;需要新一帧的外触发信号能够中断当前帧的采集&#xff0c;开始新的一帧。这需要将Buffer设为Variable Length。…

【云原生】k8s之HPA,命名空间资源限制

内容预知 1.HPA的相关知识 2.HPA的部署运用 2.1 进行HPA的部署设置 2.2 HPA伸缩的测试演示 &#xff08;1&#xff09;创建一个用于测试的pod资源 (2)创建HPA控制器&#xff0c;进行资源的限制&#xff0c;伸缩管理 &#xff08;3&#xff09;进入其中一个pod容器仲&#xf…