/**
*求二叉树的高度
* 整棵树的高度 = Math.max(左树高度, 右树高度) + 1
* root会把每个节点都走一遍 时间复杂度o(N)
* @param root
* @return
*/
public int getHeight(TreeNode root) {
if(root == null) {
return 0;
}
int leftHeight = getHeight(root.left);
int rightHeight = getHeight(root.right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
//这样写会存在超出运行时间的问题
//return getHeight(root.left) > getHeight(root.right) ? getHeight(root.left) + 1 : getHeight(root.right) + 1;
}
/**判断两棵树是否相同
* 时间复杂度: O(min(m,n))
* @param p m个节点
* @param q n个节点
* @return
*/
public boolean isSameTree(TreeNode p, TreeNode q) {
/*
根节点的结构和值一样 => p和q都不为空并且p和q的值一样
左子树的结构和值一样 && 右子树的结构和值一样 => p.left q.left && p.right q.right
*/
//1.一个为空 一个不为空 [结构上不一样]
if(p != null && q == null || p == null && q != null){
return false;
}
//2.第一步走完之后,要么都为空,要么都不为空 两个都是空
if(p == null && q == null){
return true;
}
//3.都不为空
if(p.val != q.val){
return false;
}
//4.此时代表2个都不为空同时val值也是一样的!
//5.说明根节点相同,接下来判断两棵树的左和两棵树的右是不是同时相同
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
}
/** 判断一棵树是否为另一棵树的子树
* 时间复杂度:O(m*n)
* @param root m
* @param subRoot n
* @return
*/
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
/*
1.去判断两棵树是不是两棵相同的树
2.如果不是两棵相同的树,那么有可能是root的左子树的子树也有可能是root右子树的子树
*/
if(root == null) {
return false;
}
if(isSameTree(root, subRoot)) {
return true;
}
if(isSubtree(root.left, subRoot)) {
return true;
}
if(isSubtree(root.right, subRoot)) {
return true;
}
return false;
}
/**翻转二叉树
* 时间复杂度:
* @param root
* @return
*/
public TreeNode invertTree(TreeNode root) {
if(root == null) {
return null;
}
//减少一些递归和交换的次数
if(root.left == null && root.right == null) {
return root;
}
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
invertTree(root.left);
invertTree(root.right);
return root;
}
平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1。
/**平衡二叉树
*时间复杂度:O(N^2)
* @param root
* @return
*/
//1.当前root的左子树和右子树的高度差 <= 1
//2.同时满足 root的左子树平衡 && root的右子树平衡
public boolean isBalanced(TreeNode root) {
if(root == null) {
return true;
}
int leftH = maxDepth(root.left);
int rightH = maxDepth(root.right);
return Math.abs(leftH - rightH) <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
public int maxDepth(TreeNode root) {
if(root == null) {
return 0;
}
int leftHeight = maxDepth(root.left);
int rightHeight = maxDepth(root.right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
/**平衡二叉树优化
*时间复杂度:O(N)
* @param root
* @return
*/
public boolean isBalanced2(TreeNode root) {
if(root == null) {
return true;
}
return maxDepth2(root) >= 1;
}
public int maxDepth2(TreeNode root) {
if(root == null) {
return 0;
}
int leftHeight = maxDepth2(root.left);
if(leftHeight < 0) {
return -1;
}
int rightHeight = maxDepth2(root.right);
if(rightHeight < 0) {
return -1;
}
if(Math.abs(leftHeight - rightHeight) <= 1) {
return Math.max(leftHeight, rightHeight) + 1;
}else {
return -1;
}
}
/**对称二叉树
* 时间复杂度:O(N)
* @param root
* @return
*/
public boolean isSymmetric(TreeNode root) {
if(root == null) {
return true;
}
return isSymmetricChild(root.left, root.right);
}
public boolean isSymmetricChild(TreeNode leftTree, TreeNode rightTree) {
//1.检查结构是否相同 -> 一个为空 一个不为空
if(leftTree != null && rightTree == null ||
leftTree == null && rightTree != null) {
return false;
}
//2.检查结构是否相同 -> 处理【两个都为空】和两个都不为空
if(leftTree == null && rightTree == null) {
return true;
}
//3.检查结构是否相同 -> 处理两个都为空和【两个都不为空,判断值一样吗】
if(leftTree.val != rightTree.val) {
return false;
}
//4.此时两个引用都不为空同时节点的值一样
//5.开始判断是否对称
//6.满足左子树的左和右子树的右对称同时左子树的右和右子树的左对称
return isSymmetricChild(leftTree.left, rightTree.right) &&
isSymmetricChild(leftTree.right, rightTree.left);
}