判断一个树是否为二叉查找树
一开始还以为这个问题很简单,平时练习的时候也没有多在意,直到。。。百度二面后一个算法加面以及字节跳动视频面都出现了这个问题,才发现并不是想象中的那么简单。
找了别人的几篇博客看了看,发现别人好像都有过总结。。就有点尴尬,想来想去还是记录下来吧,敲一遍印象更深。。。【我只是代码的搬运工】
———————————————– 我是正文分割线————————————————–
1. 二叉查找树定义?性质?
任意一个节点的值一定大于该节点左子树中的任意一个节点的值,同时满足该节点的值小于其右子树中的任意一个节点的值。
2. 二叉查找树数据结构定义(个人版本)
class TreeNode{int data;TreeNode left;TreeNode right;//构造函数 ....
}
3. 错误方法
很不好意思的是,这两次面试每次遇到这个问题总是脱口而出:
“递归判断每个节点和其左右节点值的大小关系”
非常遗憾,这种方法是错误的 是错误的 是错误的 是错误的 是错误的,只能判断是否为局部二叉查找树,反例就是这个:
先不管是否正确吧,这个方法的思路如下:
public boolean isTree(TreeNode root){if(root == null) return true;if(root.left != null && root.left.val > root.val)return false;if(root.right != null && root.right.val < root.val)return false;if(!isTree(root.left) || !isTree(root.right))return false;return true;
}
4. 使用中序遍历判断二叉查找树(保存到数组中)
这个方法的思路也很简单,根据二叉查找树的性质我们可以知道:如果我们用中序遍历遍历二叉查找树的话,遍历到的每个节点是依次增大的。根据这个思路,我们可以遍历一遍树,将遍历到的值保存到数组中,然后再判断这个数组是否为递增数组就可以了。下面是算法片段:
List<Integer> list=new ArrayLIst<>();
public void isTree(TreeNode root){if(root == NULL) return;isTree(root.left);list.add(root.val);isTree(root.right);
}
public static void main(String[] args){//假设给定了树的根节点rootisTree(root);for(int i = 1; i < list.size(); i++)if(list.get(i-1) >= list.get(i]))return false;return true;
}
5. 使用中序遍历判断二叉查找树(保存中序遍历上一个节点值)
每当我说可以用数组保存遍历顺序,然后判断数组是否为递增数组后,面试官总会问“还有没有更简单的方法,使用O(1)的空间复杂度?”
其实面试官的意思就是:只让你保存遍历节点的上一个节点值,不需要另外开辟空间。因为中序遍历是递增的,所以只需要比较上一个节点值和该节点值的大小即可。递归算法思路就是如下:
int last = Integer.MIN_VALUE;
public boolean isTree(TreeNode root){if(root == null) return true;if(!isTree(root.left)) return false;if(root.val <= last) return false;last=root.val;if(!isTree(root.right)) return false;return true;
}
有的时候面试官还要问能不能用迭代写出来,我就一块写一下吧。迭代算法思路就是使用栈进行存储,先将左子树压入栈,然后依次取出判断。代码如下:
public boolean isBST(TreeNode root) {Stack<TreeNode> stack = new Stack<>();TreeNode p = root, pre =n ull;while(p != null || !stack.isEmpty()){while(p != null){stack.push(p);p = p.left;} TreeNode t = stack.pop();if(pre != null && t.val <= pre.val)return false;pre = t;p = t.right; }return true;
}
6. 使用Morris Traversal方法
这个方法也是从别人那里看到的一种遍历二叉树的方法,不用栈存储而且为空间复杂度为O(1)。思路就是利用叶子节点中的左右空指针指向中序遍历下的前驱节点或后继节点,从而得到判断条件。在一开始last我用的是int last=Ineger.MIN_VALUE
结果在leetcode上跑的时候有个测试用例是 -2147483648,正好是MIN_VALUE,然后就判断错误,于是用了其包装类型。代码如下:
public boolean isValidBST(TreeNode root) {if(root == null) return true;Integer last = null;TreeNode cur=root, pre=null;while(cur != null){if(cur.left != null){pre = cur.left;while(pre.right != null && pre.right != cur)pre = pre.right;if(pre.right == null){pre.right = cur;cur = cur.left;}else{pre.right = null;if(last != null && cur.val <= last)return false;last = cur.val;cur = cur.right;} }else{if(last != null && cur.val <= last)return false;last = cur.val;cur = cur.right;}}return true;}
6. 参考文章
当然,还有好多方法没有写出来,比如说这个: https://blog.csdn.net/FlushHip/article/details/70941221 用每个子树的最大最小值和根节点值比较得到结果。
感谢一下大神提供思路以及代码。。。
递归非递归方法
https://blog.csdn.net/qq_30490125/article/details/53135274
Morris Traversal方法
https://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html
Leetcode上题目
https://leetcode-cn.com/problems/validate-binary-search-tree
判断一个树是否为二叉查找树相关推荐
- 【IT笔试面试题整理】判断一个树是否是另一个的子树
[试题描述]定义一个函数,输入判断一个树是否是另一个对的子树 You have two very large binary trees: T1, with millions of nodes, and ...
- 用python判断一个树是否为素数(质数)
输入一个数,判断其是否为素数(除了自己和1,没有别的因子) while True: 无限循环判断 m = int(raw_input('请输入一个整数:')) if m > ...
- 利用KMP算法判断一个树是否是另一个树的子树
方法:利用KMP算法,将两个树进行序列化,分别遍历一遍树,得到两个字符串,时间复杂度是O(n) KMP问题: String1,String2,如果String2为String1的子串,则返回Strin ...
- 判断一个图是否为树(有向图以及无向图)
整理的算法模板合集: ACM模板 目录 判断一个图是否为树 1. 无向图(hdu 1272 小希的迷宫) 2. 有向图(hdu 1325 Is It A Tree?) 判断一个图是否为树 1. 无向图 ...
- 【数据结构】-图-判断一个无向图是否是一棵树
思路:判断一个无向图是否是一棵树,只需要判断该图是否是一个包含n个顶点的连通子图且边数为n-1,只要这两个条件都满足,那么就是一棵树. 因此我们可以采用深度遍历,若图连通,那么只要一次深度遍历就可以遍 ...
- 数据结构与算法(java):树-二叉树(二叉查找树(BST)、线索化二叉树、哈夫曼树、平衡二叉树【AVL】、二叉树的前中后序遍历)
二叉树 1.定义 二叉树 就是度不超过2的树(每个结点最多只有两个子结点).如图 2.特殊二叉树 满二叉树 当二叉树的每一个层的结点树都达到最大值,则这个二叉树就是满二叉树. 完全二叉树 叶结点只能出 ...
- 如何去判断一个面试者的深度学习水平?
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 编辑:Amusi | 来源:知乎 https://www.zhi ...
- AVL树---平衡的二叉查找树
AVL树是每个结点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1). 它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度. AVL树的性质: 左子树和右子树的高度差 ...
- 左神算法:判断 t1 树是否包含t2 树全部的拓扑结构(剑指 Offer 26. 树的子结构,Java版)
本题来自左神<程序员代码面试指南>"判断 t1 树是否包含t2 树全部的拓扑结构"题目. 题目 剑指 Offer 26. 树的子结构 给定彼此独立的两棵树头节点分别为 ...
最新文章
- MIT发布首个贝叶斯「数据清洗」机器人!8小时洗200万条数据
- Socket连接与HTTP连接
- mysql using filesort_mysql using filesort Using temporary
- ABP从入门到精通(4):使用基于JWT标准的Token访问WebApi
- 机器成为家人!华为发布2025十大趋势展望...
- 音乐在线播放Demo
- 转: DH密钥交换和ECDH原理
- 上下文路径request.getContextPath();与${pageContext.request.contextPath}
- 3D游戏开发套件指南(入门篇,转自Unity官方平台公众号)
- CSS 常见布局 水平垂直居中对齐
- 位移的单位符号_初中物理符号级单位符号公式大全
- UE4_模型_Bound(边界)
- ChucK初步(2)
- PC传输图片到Hololens
- 【VHDL语言学习笔记(二)】 4位向量加法器
- 全国计算机技术与软件专业技术资格(水平)考试【软件评测师】-考试内容总结(十二)软件评测基础知识...
- Spring--官方文档部分翻译(第一章)
- 目标管理的痛?那是因为你没有找准目标管理工具
- 博应用测评软件ofo小黄车和摩拜单车哪个更好骑
- 赋能数智化· 从数据到价值转变 | GCT冠骋信息高科技电子行业智能制造高端研讨会成功举办
热门文章
- linux中nginx启动,重启,关闭命令
- break语句的作用
- 送给计算机老师平安夜贺卡,平安夜送给老师的平安祝福语
- 高等工程热力学复习04
- c语言double型小数点后几位_double类型的数据在输出的时候,C语言编译器对小数部分可以精确到小数点后面的第几位?...
- java关键字super指什么_java 关键字super详解及用法
- 工作10年写不好一封邮件?
- 大数据中技术的定义和特点
- 浙大PAT 1003题 1003. Emergency
- python实现贪吃蛇小游戏