1、题目

给定一棵二叉树的根节点,判断其是否为二叉搜索树。

2、分析

二叉搜索树:每一棵子树的根节点,左子树的值比根节点的值小,右子树的值比根节点的值大。

经典的二叉搜索树是没有重复值的。如果要放重复值,那么一定是在一个节点中用某种数据结构存放着,而不是产生多个值重复的节点。

判断一棵树是否为搜索二叉树的方法:

  • 方法一:中序遍历整棵树,如果该中序遍历的序列是升序的,则是搜索二叉树,否则不是。

  • 方法二:用递归套路解决:

    ①目标:假设以 X 节点为根的二叉树是否为搜索二叉树;

    ②可能性:通过向左树获得某些信息,向右树获得某些信息的情况下来列举可能性;

    ③ X 是搜索二叉树的原则:
    (1)X左树是搜索二叉树;
    (2)X右树是搜索二叉树;
    (3)X左树的最大值 < X节点的值;
    (4)X节点的值 < X 右树的最小值;

    所以对于每一个子树的根节点,只需要上面 4 个信息就能支持判断该子树是否为搜索二叉树。

    整理可得,需要向左树获得信息:1. 是否为搜索二叉树;2. 最大值。

    向右树获得信息:1. 是否为搜索二叉树;2. 最小值。

    此时发现向左树和右树需要获得的信息不一样,怎么办呢?求全集!!

    即是说,向左树和右树都需要获得信息包括(1)是否为搜索二叉树;(2)最大值;(3)最小值。

    递归对所有的节点一视同仁,不要定制任何节点的信息

3、实现

C++版

/*************************************************************************> File Name: 035.判断二叉树是否为二叉搜索树.cpp> Author: Maureen > Mail: Maureen@qq.com > Created Time: 五  7/ 1 15:56:01 2022************************************************************************/#include <iostream>
#include <ctime>
#include <vector>
using namespace std;class TreeNode {public:int value;TreeNode *left;TreeNode *right;TreeNode(int data) : value(data) {}
};//方法一: 中序遍历
void inOrder(TreeNode *node, vector<int> &arr) {if (node == nullptr) return ;inOrder(node->left, arr);arr.push_back(node->value);inOrder(node->right, arr);
}bool process1(TreeNode *root) {vector<int> ans;inOrder(root, ans);for (int i = 1; i < ans.size(); i++) {if (ans[i - 1] > ans[i]) return false;}return true;
}bool isBST1(TreeNode *root) {if (root == nullptr) return true;return process1(root);
}//方法二:二叉树的递归套路
class Info {public:bool isBST;int maxVal;int minVal;Info(bool i, int ma, int mi) : isBST(i), maxVal(ma), minVal(mi) {}
};Info *process2(TreeNode *root) {if (root == nullptr) {return nullptr;}//获取左树信息Info *leftInfo = process2(root->left);//获取右树信息Info *rightInfo = process2(root->right);//设置最值int maxVal = root->value;int minVal = root->value;//左树不为空, 更新最值if (leftInfo != nullptr) {maxVal = max(maxVal, leftInfo->maxVal);minVal = min(minVal, leftInfo->minVal);}//右树不为空,更新最值if (rightInfo != nullptr) {maxVal = max(maxVal, rightInfo->maxVal);minVal = min(minVal, rightInfo->minVal);}bool isBST = true;//左树不为空,且左树的最大值 >= 根节点的值if (leftInfo != nullptr && (!leftInfo->isBST || leftInfo->maxVal >= root->value) ) {isBST = false;}//右树不为空,且右树的最小值 <= 根节点的值if (rightInfo != nullptr && (!rightInfo->isBST || rightInfo->minVal <= root->value) ) {isBST = false;}return new Info(isBST, maxVal, minVal);
}bool isBST2(TreeNode *root) {if (root == nullptr) return true;return process2(root)->isBST;
}//for test
TreeNode *generate(int level, int maxlevel, int maxval) {if (level > maxlevel || (rand() % 100 / 101) < 0.5) return nullptr;TreeNode *root = new TreeNode(rand() % maxval);root->left = generate(level + 1, maxlevel, maxval);root->right = generate(level + 1, maxlevel, maxval);return root;
}TreeNode *generateRandomBST(int maxlevel, int maxval) {return generate(1, maxlevel, maxval);
}int main() {srand(time(0));int level = 4;int value = 100;int testTime = 1000001;for (int i = 0; i < testTime; i++) {TreeNode *root = generateRandomBST(level, value);if (isBST1(root) != isBST2(root)) {cout << "Failed!" << endl;return 0;}}cout << "Success!" << endl;return 0;
}

Java 版

import java.util.ArrayList;
public class isBST {public static class Node {public int value;public Node left;public Node right;public Node(int data) {this.value = data;}}//方法一:public static boolean isBST1(Node head) {if (head == null) {return true;}ArrayList<Node> arr = new ArrayList<>();in(head, arr);for (int i = 1; i < arr.size(); i++) {if (arr.get(i).value <= arr.get(i - 1).value) {return false;}}return true;}public static void in(Node head, ArrayList<Node> arr) {if (head == null) {return;}in(head.left, arr);arr.add(head);in(head.right, arr);}//方法二:使用递归套路public static boolean isBST2(Node head) {if (head == null) return true;return process2(head).isBST;}public static class Info {boolean isBST; //是否为搜索二叉树public int min; //最小值public int max; //最大值public Info(boolean is, int mi, int ma) {isBST = is;min = mi;max = ma;}}//自己实现了这些信息,才能在递归中从左右子树中获取相同的信息public static Info process2(Node x) {//空树不好设置min和max,于是直接返回空,让上游调用者处理if (x == null) { return null;}//向左树获取信息Info leftInfo = process2(x.left);//向右树获取信息Info rightInfo = process2(x.right);//将获取的信息填充到Info中,就能知道当前x节点是否为搜索二叉树int min = x.value;int max = x.value;if (leftInfo != null) {max = Math.max(max, leftInfo.max);min = Math.min(min, leftInfo.min);}if (rightInfo != null) {max = Math.max(max, rightInfo.max);min = Math.min(min, rightInfo.min);}boolean isBST = true;//左树不为空,但是左树不是搜索二叉树if (leftInfo != null && !leftInfo.isBST) {isBST = false;}//右树不为空,但是左树不是搜索二叉树if (rightInfo != null && !rightInfo.isBST) {isBST = false;}//左树不为空,但是左树的最大值>=x节点的值if (leftInfo != null && leftInfo.max >= x.value) {isBST = false;}//右树不为空,但是右树的最小值<=x节点的值if (rightInfo != null && rightInfo.min <= x.value) {isBST = false;}return new Info(isBST, min, max);}//对数器// for testpublic static Node generateRandomBST(int maxLevel, int maxValue) {return generate(1, maxLevel, maxValue);}// for testpublic static Node generate(int level, int maxLevel, int maxValue) {if (level > maxLevel || Math.random() < 0.5) {return null;}Node head = new Node((int) (Math.random() * maxValue));head.left = generate(level + 1, maxLevel, maxValue);head.right = generate(level + 1, maxLevel, maxValue);return head;}public static void main(String[] args) {int maxLevel = 4;int maxValue = 100;int testTimes = 1000000;for (int i = 0; i < testTimes; i++) {Node head = generateRandomBST(maxLevel, maxValue);if (isBST1(head) != isBST2(head)) {System.out.println("Oops!");}}System.out.println("finish!");}
}

判断二叉树是否为二叉搜索树相关推荐

  1. C语言判断二叉树是否为二叉搜索树(附完整源码)

    C语言判断二叉树是否为二叉搜索树 C语言判断二叉树是否为二叉搜索树完整源码(定义,实现,main函数测试) C语言判断二叉树是否为二叉搜索树完整源码(定义,实现,main函数测试) #include ...

  2. c++判断二叉树是否为二叉搜索树_原创 | 好端端的数据结构,为什么叫它SB树呢?...

    点击上方蓝字,关注并星标,和我一起学技术. 大家好,今天给大家介绍一个很厉害的数据结构,它的名字就很厉害,叫SB树,业内大佬往往叫做傻叉树.这个真不是我框你们,而是它的英文缩写就叫SBT. SBT其实 ...

  3. 按照层次序列创建二叉树,并判断二叉树是否为二叉搜索树

    首先定义树节点的数据结构,如下: struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; 两个函数,用 ...

  4. 判定一棵二叉树是否是二叉搜索树

    问题 给定一棵二叉树,判定该二叉树是否是二叉搜索树(Binary Search Tree)? 解法1:暴力搜索 首先说明一下二叉树和二叉搜索树的区别.二叉树指这样的树结构,它的每个结点的孩子数目最多为 ...

  5. 二叉树(二):判断是不是二叉搜索树、判断是不是完全二叉树、判断是不是平衡二叉树、二叉搜索树的最近公共祖先、在二叉搜索树中找到两个节点的最近公共祖先、序列化二叉树、重建二叉树、输出二叉树的右视图

    目录 一.判断是不是二叉搜索树 1.1 题目 1.2 题解 二.判断是不是完全二叉树 2.1 题目 2.2 题解 三.判断是不是平衡二叉树 3.1 题目 3.2 题解 四.二叉搜索树的最近公共祖先 4 ...

  6. 判断一颗二叉树是否为二叉搜索树(Validate Binary Search Tree)

    一.学习要点: 利用二叉搜索树的中序遍历为递增数组的性质: 二.代码: void middle(node* root,vector<int>& inorder) {if(root= ...

  7. C++初阶学习————二叉树进阶(二叉搜索树)

    二叉树进阶 二叉搜索树的概念 二叉搜索树的操作 基本框架 二叉搜索树的插入 二叉搜索树的查找 二叉搜索树的删除 整体代码 循环写法 递归写法 二叉搜索树的应用 二叉搜索树的性能分析 前面的文章介绍过二 ...

  8. 二叉树OJ(一)二叉树的最大深度 二叉搜索树与双向链表 对称的二叉树

    二叉树的最大深度 二叉树中和为某一值的路径(一) 二叉搜索树与双向链表 对称的二叉树 二叉树的最大深度 描述 求给定二叉树的最大深度, 深度是指树的根节点到任一叶子节点路径上节点的数量. 最大深度是所 ...

  9. 【C++】二叉树进阶(二叉搜索树)

    文章目录 前言 1.二叉搜索树 1-1. 二叉搜索树概念 2.二叉搜索树操作 2-1.树和节点的基本框架 2-2.二叉搜索树的查找 2-3.中序遍历 2-4.二叉搜索树的插入 2-5.二叉搜索树的删除 ...

最新文章

  1. oracle 常用sql
  2. pypthon3精要(16)-enumerate
  3. 多元高斯分布(Multivariate Gaussian Distribution)
  4. c语言编译前端,c语言编译器前端的设计与实现.doc
  5. MySQL外键约束详解
  6. Mac 终端以及常用终端命令
  7. 不显示藏宝阁试穿服务器,梦幻西游:藏宝阁试穿功能的妙用,无限回档测试
  8. Mybatis Sql 大于号小于号不兼容
  9. rocketmq 两个线程同时消费一个消息
  10. Java Lambda 策略模式
  11. 我的PCB设计经验——奥研电子整理
  12. android6 存储卡异常,手机SD卡无法读取时,如何在手机上修复损坏的SD卡?
  13. 【Unity】基于顶点色的海边波浪效果(适用移动端)
  14. Charles-iOS安装证书
  15. 评:日本的“泡沫”代价
  16. JAVA基础语法(1)
  17. C++中rand()函数的用法
  18. 平价无线蓝牙耳机推荐,小米和南卡蓝牙耳机哪个好用?
  19. 如何从零开发一个低代码平台,有哪些成熟技术组件可用
  20. 对言语上的自律和真正的自律的一些想法

热门文章

  1. 牛客_给出股票价格找出买入点和卖出点让利润最大化
  2. 25_PyTorch的十九个损失函数(L1Loss、MSELoss、CrossEntropyLoss 、CTCLoss、NLLLoss、PoissonNLLLoss 、KLDivLoss等)
  3. Focal Loss 论文理解及公式推导
  4. 说说社会化媒体营销的困境
  5. 系统思考:智猪博弈(指定战略)
  6. 程序设计原则(总结)
  7. 致敬一个时代的谢幕||老佛爷Karl Lagerfeld
  8. 别了,我的第一份正式工作!!
  9. a算法TSP旅行商java_A*算法解决旅行商问题
  10. Alcatel-Lucent 7750 运营商认证设备在线用户数OID