中序遍历二叉搜索树,得到的值序列是有序序列。因此,中序遍历二叉树,访问某个节点的时候,如果出现了反序情况,那么表明该树不是二叉搜索树。
层序遍历完全二叉树,判断孩子是否存在,存在则进入状态1,不存在则进入状态0,则层序遍历完全二叉树满足状态机:s → 状态1 → 状态0 → e,其中状态1和状态0有自旋边。如果遍历二叉树时,出现状态0变成状态1的情况,那么表明该树不是完全二叉树。
import java.util.*;
public class Solution {
/**
* 二叉搜索树的全局顺序,-1表示由小到大,0表示全等,1表示由大到小。
*/
private int order;
/**
* 中序遍历二叉搜索树,上一个被访问节点的值。
*/
private int lastVal;
/**
* @param root TreeNode类 the root
* @return bool布尔型一维数组
*/
public boolean[] judgeIt(TreeNode root) {
TreeNode p = root;
int min = 0;
int max = 0;
while (p != null){
min = p.val;
p = p.left;
}
p = root;
while (p != null){
max = p.val;
p = p.right;
}
order = Integer.signum(min - max);
lastVal = min;
boolean[] result = new boolean[2];
result[0] = dfs(root);// 判断是否为二叉搜索树。
result[1] = bfs(root);// 判断是否为完全二叉树。
return result;
}
/**
* 层序遍历二叉树,判断树是否为完全二叉树。当前孩子存在(即不为null)则表示①,不存在则表示零。
* 完全二叉树满足状态机 s → ① → 零 → e。①和零有自旋边。
* @param root
* @return
*/
private boolean bfs(TreeNode root) {
if (root == null) return true;
Deque<TreeNode> queue = new ArrayDeque<>();
queue.add(root);
int lastState = 1;// 上一个状态值。
while (!queue.isEmpty()){
TreeNode currNode = queue.remove();
if (currNode.left == null){
lastState = 0;
}
else {
if (lastState == 0) return false;// 当前状态是1(表示当前孩子存在),不能由上个状态0返回状态1。
queue.add(currNode.left);
}
if (currNode.right == null){
lastState = 0;
}
else {
if (lastState == 0) return false;// 当前状态是1(表示当前孩子存在),不能由上个状态0返回状态1。
queue.add(currNode.right);
}
}
return true;
}
/**
* 中序遍历二叉树,如果访问的节点值由小到大/由大到小,那么该二叉树是二叉搜索树。
* @param root
* @return
*/
private boolean dfs(TreeNode root) {
if (root == null) return true;
if (!dfs(root.left)) return false;// 左子树不是二叉搜索树。
// 访问当前节点
int currOrder = Integer.signum(lastVal - root.val);// 局部顺序。-1表示由小到大,0表示全等,1表示由大到小。
if (currOrder != 0 && order != currOrder) return false;// 左子树加当前节点不满足二叉搜索树的要求。
// 准备访问下一个节点
lastVal = root.val;
// 左子树加当前节点已满足二叉搜索树的要求,由右子树最终判定整棵树是否为二叉搜索树。
return dfs(root.right);
}
}