首先要知道什么是二叉搜索树(二叉排序树)(二叉查找树) :
例如下面的树就是一颗二叉搜索树 :
怎么判断一颗二叉树是不是搜索二叉树呢? 其实很简单,只要这颗二叉树的中序遍历的顺序是升序的,那么就是一颗二叉搜索树,因为中序遍历的顺序是 左->中->右 ,所以当中序遍历升序的时候,就有左<中<右,所以就可以判断。
class Solution {
public boolean isValidBST(TreeNode root) {
if(root == null)
return true;
Stack<TreeNode>stack = new Stack<>();
TreeNode cur = root;
TreeNode pre = null;
while(!stack.isEmpty() || cur != null){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else {
cur = stack.pop();
if(pre != null && cur.val <= pre.val)
return false;
pre = cur;
cur = cur.right;
}
}
return true;
}
}
代码中使用的是非递归的中序遍历,不懂的可以看这个博客。
当然也可以使用中序的递归,记录一个全局的pre
变量:
class Solution {
private TreeNode pre;
public boolean isValidBST(TreeNode root) {
if(root == null)
return true;
pre = null;
return inOrder(root);
}
private boolean inOrder(TreeNode node){
if(node == null)
return true;
if(!inOrder(node.left))
return false;
if(pre != null && node.val <= pre.val)
return false;
pre = node;
if(!inOrder(node.right))
return false;
return true;
}
}
还有一种解法就是利用左右两边的min
和max
:
node
,node在中序遍历中的前一个结点pre
的值min
,node
在中序遍历中的后一个节点next
的值max
;min < node.val && node.val < max
,如果不满足就返回false
;class Solution {
public boolean isValidBST(TreeNode root) {
if(root == null)
return true;
return helper(root,null,null);
}
//min、max 也可以看做是 pre、next 就是root的前一个、后一个
private boolean helper(TreeNode node,Integer min,Integer max){
if(node == null)
return true;
//先判断自己
if( (min != null && node.val <= min) || (max != null && node.val >= max) )
return false;
// 判断左孩子
if( !helper(node.left,min,node.val))
return false;
//判断右孩子
if( !helper(node.right,node.val,max))
return false;
return true;
}
}
这里还需要注意当node = Integer.MIN_VALUE
或者Integer.MAX_VALUE
这两个值的影响。
首先知道什么是完全二叉树:
K
,且结点总数是(2k) -1 ,则它就是满二叉树)而引出来的。对于深度为K
的,有n
个结点的二叉树,当且仅当其每一个结点都与深度为K
的满二叉树中编号从1
至n
的结点一一对应时称之为完全二叉树。h
,除第 h
层外,其它各层 (1~h-1)
的结点数都达到最大个数,第h
层所有的结点都连续集中在最左边,这就是完全二叉树。2
,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。那么如何判断一棵二叉树是否为完全二叉树呢? 按照下面的标准 :
false
;false
;false
,就返回true
;怎么理解上面的过程呢?
false
。如下:所以综上,我们就可以写出代码,使用层次遍历,用一个bool
型变量leaf
记录是否遇到了左右孩子是不是不全的情况(这时就开始判断后面的结点是不是叶子结点),代码如下 :
//判断一棵二叉树是不是完全二叉树
static boolean isCBT(TreeNode root){
if(root == null)
return true;
Queue<TreeNode>queue = new LinkedList<>();
boolean leaf = false; //如果碰到了 某个结点孩子不全就开始 判断是不是叶子这个过程
queue.add(root);
TreeNode top = null,L = null,R = null;
while(!queue.isEmpty()){
top = queue.poll();
L = top.left; R = top.right;
//第一种情况
if((R != null && L == null))
return false;
//第二种情况 开启了判断叶子的过程 而且又不是叶子 就返回false
if(leaf && (L != null || R != null)) //以后的结点必须是 左右孩子都是null
return false;
if(L != null)
queue.add(L);
//准确的说是 只要孩子不全就开启leaf,
//但是前面已经否定了有右无左的情况,这里只要判断一下右孩子是不是为空就可以了(如果为空就开启leaf)
if(R != null)
queue.add(R);
else
leaf = true;
}
return true;
}
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* 判断一棵二叉树是否为搜索二叉树
* 判断一棵二叉树是否为完全二叉树
*/
public class IsBSTAndCBT {
static class TreeNode{
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int value) {
this.val = value;
}
}
static boolean isBST(TreeNode root){
if(root == null)
return true;
Stack<TreeNode>stack = new Stack<>();
TreeNode cur = root;
TreeNode pre = null;
while(!stack.isEmpty() || cur != null){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else {
cur = stack.pop();
if(pre != null && cur.val <= pre.val)
return false;
pre = cur;
cur = cur.right;
}
}
return true;
}
//判断一棵二叉树是不是完全二叉树
static boolean isCBT(TreeNode root){
if(root == null)
return true;
Queue<TreeNode>queue = new LinkedList<>();
boolean leaf = false; //如果碰到了 某个结点孩子不全就开始 判断是不是叶子这个过程
queue.add(root);
TreeNode top = null,L = null,R = null;
while(!queue.isEmpty()){
top = queue.poll();
L = top.left; R = top.right;
//第一种情况
if((R != null && L == null))
return false;
//第二种情况 开启了判断叶子的过程 而且又不是叶子 就返回false
if(leaf && (L != null || R != null)) //以后的结点必须是 左右孩子都是null
return false;
if(L != null)
queue.add(L);
//准确的说是 只要孩子不全就开启leaf,
//但是前面已经否定了有右无左的情况,这里只要判断一下右孩子是不是为空就可以了(如果为空就开启leaf)
if(R != null)
queue.add(R);
else
leaf = true;
}
return true;
}
public static void main(String[] args) {
System.out.println("===============test for BST================");
System.out.println("---------test1--------------");
TreeNode head = new TreeNode(1);
System.out.println(isBST(head));//true
System.out.println("---------test2--------------");
head = new TreeNode(2);
head.left = new TreeNode(1);
head.right = new TreeNode(3);
System.out.println(isBST(head));//true
System.out.println("---------test3--------------");
head = new TreeNode(2);
head.left = new TreeNode(1);
head.right = new TreeNode(0);
System.out.println(isBST(head));//false
System.out.println("---------test4(for example)--------------");
head = new TreeNode(5);
head.left = new TreeNode(3);
head.left.left = new TreeNode(2);
head.left.right = new TreeNode(4);
head.left.left.left = new TreeNode(1);
head.right = new TreeNode(8);
head.right.left = new TreeNode(6);
head.right.left.right = new TreeNode(7);
head.right.right = new TreeNode(10);
head.right.right.left = new TreeNode(9);
System.out.println(isBST(head));
System.out.println();
System.out.println("===============test for CBT================");
head = new TreeNode(1);
head.left = new TreeNode(2);
head.left.left = new TreeNode(4);
head.left.right = new TreeNode(5);
head.left.left.left = new TreeNode(8);
head.left.left.right = new TreeNode(9);
head.left.right.right = new TreeNode(10); //false
head.right = new TreeNode(3);
head.right.left = new TreeNode(6);
head.right.right = new TreeNode(7);
System.out.println(isCBT(head));
head = new TreeNode(1);
head.left = new TreeNode(2);
head.left.left = new TreeNode(4);
head.left.right = new TreeNode(5);
head.left.left.left = new TreeNode(8);
head.left.left.right = new TreeNode(9);
head.left.right.left = new TreeNode(10); //true
head.right = new TreeNode(3);
head.right.left = new TreeNode(6);
head.right.right = new TreeNode(7);
System.out.println(isCBT(head));
head = new TreeNode(1);
head.left = new TreeNode(2);
head.left.left = new TreeNode(4);
head.left.right = new TreeNode(5);
head.left.left.left = new TreeNode(8);
head.left.left.right = new TreeNode(9);
// head.left.right.left = new TreeNode(10); //true
head.right = new TreeNode(3);
head.right.left = new TreeNode(6);
head.right.right = new TreeNode(7);
System.out.println(isCBT(head));
}
}