过程如下:
- 如果head==null,直接返回0
- 如果不是空树,就求树的高度,求法是找到树的最左边节点,看能到哪一层。层数记为h
- 接下来就是具体的逻辑,是通过一个递归函数来实现的,bs(node,l,h),node表示当前节点,l表示node所在的层数,h表示整棵树的层数,是始终不变的。bs(node,l,h)返回值表示以node为头的完全二叉树的节点数,初始时node为头节点head,l为1,具体过程可以用下面的例子来说明:
就像上面这个图,从根节点开始,节点右子树的最左节点,能到达最后一层,所以此时根节点的左子树是蛮叉树,并且层数为h-l层,其节点个数为2^(h-l) -1个,如果再加上它自己就是2^ (h-l)个。如果当前节点的右子树的最左节点到达不了最后一层,如下图:
说明此时当前节点的右子树是满二叉树,其节点个数加上自己为2^(h-l-1)个。具体代码如下:
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
}
public static int nodeNum(Node head) {
if (head == null) {
return 0;
}
return bs(head, 1, mostLeftLevel(head, 1));
}
public static int bs(Node node, int l, int h) {
if (l == h) { //只有一个节点的时候直接返回1 //这是递归的终止条件
return 1;
}
if (mostLeftLevel(node.right, l + 1) == h) {
return (1 << (h - l)) + bs(node.right, l + 1, h); //这个是逻辑左移相当于是2的幂
} else {
return (1 << (h - l - 1)) + bs(node.left, l + 1, h);
}
}
public static int mostLeftLevel(Node node, int level) {
while (node != null) {
level++;
node = node.left;
}
return level - 1; //这个是求当前节点的左子树所能到达的最深的层次,注意返回的时候要减1,因为它最终的结果要比实际的要多1
}