1、求总结点个数
很明确,就是求该二叉树总共有多少节点数。那么,一棵二叉树节点之和就等于根节点+左子树节点数+右子树节点数。而左/右子树又可以看成一棵新的二叉树,节点数依然等于左右子树的根节点+其左右子树的节点数,依次类推。
题解关键:整体问题拆分成小问题------》每一个子树的节点等于左子树节点数+右子树节点数+根节点
对于上面节点总数的求法,我们不难看出可以采用递归的求法。
代码:
public int getNodeNumber( BTNode root)
{
if(root==null)
{
return 0;
}
return getNodeNumber(root.left)+getNodeNumber(root.right)+1;
}
2、求叶子结点个数
叶子节点:左右节点都为空的节点叫做叶子节点。
因此,我们只需要遍历每个节点,当其左右孩子都为null时,数值+1,即可得到叶子节点总数。我们采用前序遍历来遍历该树。
public int getLeafNodeCount( BTNode root)
{
if(root==null)
{
return 0;
}
if(root.left==null && root.right==null)
{
return 1;
}
return getLeafNodeCount(root.left)+getLeafNodeCount(root.right);
}
3、求第 k 层结点个数
获取第k层的节点个数==》相当于求k-1层,即这棵树的k-1层节点的左右孩子个数之和
如上图所示,假如我们要求第三层的节点书,就相当于求第二层(k-1)的左右孩子总数。
代码:
public int getKLevelNodeCount(BTNode root,int k)
{
if(root==null || k<=0)
{
return 0;
}
if(k==1)
{
return 1;
}
return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
}
4、获取二叉树的高度
一棵二叉树的高度其实就是左右子树的最大高度。
递归代码很简单,但是理解其中的递归细节还是有点难度,我们先来看看代码:
public int getHeight(BTNode root)
{
if(root==null)
{
return 0;
}
int leftCount=getHeight(root.left);
int rightCount=getHeight(root.right);
return leftCount>rightCount?leftCount+1:rightCount+1;
}
我们以根节点的左子树为例,来看看这个递归的过程:
- 我们从根节点(A)出发,root不为空,调用
int leftCount=getHeight(root.left);
参数root.left也就是节点B - B不为空,继续调用 int leftCount=getHeight(root.left); ,参数root.left是节点D
- D不为空,继续调用 int leftCount=getHeight(root.left); ,参数root.left是null;此时就将0返回给leftCount。即leftCount=1;
- 代码向下执行,也就是执行int rightCount=getHeight(root.right);此时的root=D,root.left=null,所以此时返回0给rightCount,,即:rightCount=0;
- 此时D节点的左子树高度为0,右子树高度为0 ,代码继续向下执行: return leftCount>rightCount?leftCount+1:rightCount+1;也就是返回给D节点的左右子树最大高度就为0;
- 然后继续向上返回到节点B,由于节点B的左子树已经遍历,此时就应该执行: int rightCount=getHeight(root.right);,此处的root=B,root.right=E;
- 和上面过程类似,向下递归,后续具体过程见上图。
5、判断这个节点是否在树中
思路:只需要遍历这棵树,对比该节点的值域是否一致,一直则返回该节点,否则返回null
代码:
public BTNode find(BTNode root,int val)
{
if(root==null)
{
return null;
}
if(root.val==val)
{
return root;
}else{
BTNode ret1=find(root.left,int val);
BTNode ret2=find(root.right,int val);
return ret1!=null?ret1:ret2;
}
}
上面代码实现了判断这个节点是否在树中,它相对于后面这种方法在递归时间上还是比较长的,来看看:
改进版:
public BTNode find(BTNode root,int val)
{
if(root==null)
{
return null;
}
if(root.val==val)
{
return root;
}
BTNode ret=null;
if(( ret=find(root.left,val)) != null || null != ( ret=find(root.right,val)))
{
return ret;
}
return null;
}
这种方法的奥妙就在于if里边的条件,巧妙地运用了或运算符。
微妙之处:
- 如果递归左子树的结果不为空(也就是在左子树中找到了这个节点),那么就不需要进行或运算符的右边了,直接将左子树的递归结果返回;
- 只有在左子树中没有找到该节点才会递归右子树。大大节省了时间效率。