根据二叉树类型 计算二叉树的节点个数
普通二叉树
如果是一颗普通的二叉树,应该怎么计算节点的个数呢?
我们可以递归每一个节点的左节点和右节点,最后加上自己,就是所有的节点个数
java代码:
//todo 计算树的节点个数(遍历)
public int getTreeNodeCount(TreeNode root){
//递归当前节点的left和right
if(root==null)return 0;
int leftCount = getTreeNodeCount(root.left);
int rightCount = getTreeNodeCount(root.right);
return leftCount+rightCount+1;
}
这种方式递归深度为logn,空间O(logn),时间为O(n)
满二叉树:
如果是一颗满二叉树呢?是否有更简单的方法呢
首先看看满二叉树的特点:
比如节点个数=2^树的深度-1。
那么
我们对于满二叉树来说只需计算它的深度即可
但是我们对于一颗二叉树来说 并不知道它是满二叉树,还是普通二叉树
所以
我们需要先判断二叉树的类型 再选择对应的简便算法 去得到这个节点的个数
java代码:
//todo 是否是完美二叉树(满二叉树)
public boolean isPerfectBinaryTree(TreeNode root){
//满二叉树的定义即 节点个数=2^高度-1。
//也就是说每一个被遍历的节点要么有俩个子节点,要么没有子节点
//所以可以 遍历每一个节点,如果该节点满足上述其中一个就递归的检查它的left和right
if(root==null)return true;//空树 -> 也是满二叉树
if((root.left==null&&root.right==null)||(root.left!=null&&root.right!=null)){
//递归left和right
boolean leftIsPerfectBinaryTree = isPerfectBinaryTree(root.left);
boolean rightIsPerfectBinaryTree = isPerfectBinaryTree(root.right);
return leftIsPerfectBinaryTree&&rightIsPerfectBinaryTree;
}else {
return false;
}
}
//todo 根据判断是否为满二叉树 来计算节点个数
public int getTreeNodeCountByPerfectTree(TreeNode root){
boolean perfectBinaryTree = isPerfectBinaryTree(root);
if(perfectBinaryTree){
//求深度,然后2^高度-1
int height=0;
while (root!=null){
root=root.left;
height++;
}
return (int) (Math.pow(2,height)-1);
}else {
return getTreeNodeCount(root);
}
}
但是这样的思路貌似比之前普通遍历要复杂一点且时间空间都没有提升。
但一般题目为给出树为满二叉树的先决条件,我们只需求一下深度再求2^深度-1即可
我这里的代码是作为学习所用
完全二叉树
那么对于完全二叉树呢?
我们再来看看完全二叉树的构造,
你会发现
只要是完全二叉树,root一定有一个子树为满二叉树。
这就给了我们一个思路
只要判断出:root的左子树是满二叉树,还是右子树是满二叉树,
如果左子树是慢二叉树,那么左子树按照满二叉树的算法去求左子树的节点个数,而右子树就按普通求法即可
如果右子树是满二叉树,则同理
那么怎么判断左右子树 谁是那颗满二叉树呢?
用俩个探头指针,一个向左下,一个右下,分别直到叶子节点,计算二者的深度,
若一致,说明该节点 就是 满二叉树的root,直接通过求幂得出该root下的节点个数
若不一致,说明它不是满二叉树的root,则直接递归left和right+1。
java代码:
//todo 完全二叉树 计算节点个数
public int getTreeNodeByCompleteTree(TreeNode root){
//完全二叉树 介于 普通二叉树-满二叉树
//而完全二叉树的子树中 必定有一颗 满二叉树
//所以我们可以 让满二叉树按照满二叉树计算方式算,普通按照普通二叉树算
//具体:遍历每一个节点,计算在当前节点对左右子树的深度,
// 若相等,说明该节点是满二叉的节点,直接返回2^深度-1
// 否则,说明该节点是普通二叉树的节点,就按普通的方式计算
TreeNode left=root,right=root;
int leftHeight=0,rightHeight=0;
while (left!=null){
left=left.left;
leftHeight++;
}
while (right!=null){
right=right.right;
rightHeight++;
}
if(leftHeight==rightHeight){
return (int) (Math.pow(2,leftHeight)-1);
}
else {
int leftCount = getTreeNodeCount(root.left);
int rightCount = getTreeNodeCount(root.right);
return leftCount+rightCount+1;
}
}