思路分析:
先遍历头结点左边界,看左边界到了那一层(假如h层),然后遍历头节点的右子树,看右子树的左边界是否到了h层
如果到了h层,则头结点的左子树是满的其节点个数为2^3-1
,加上头节点就是2^3
个,然后用同样的方法搞头节点的右子树(是个完全二叉树)
如果右子树的左边界没有到最后一层,那么右子树是满的,只是层数比左子树少一,加上头结点个数为2^2-1+1=2^2
个,此时用同样的方法搞左子树
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));
}
/**
* 返回以node为头节点的树的个数
* @param node 当前节点
* @param level 当前第几层
* @param h 树的深度
* @return
*/
public static int bs(Node node, int level, int h) {
//node在level层,level == h 则node在最后一层,即一个几点
if (level == h) {
return 1;
}
// 判断node右子树的深度是否到了h
if (mostLeftLevel(node.right, level + 1) == h) {
//1 << (h - level):左子树加上头结点的总个数,递归求右子树的节点个数
return (1 << (h - level)) + bs(node.right, level + 1, h);
} else {
// 右子树的深度没有到h,1 << (h - level - 1):右子树加上头结点的总个数,递归求左子树
return (1 << (h - level - 1)) + bs(node.left, level + 1, h);
}
}
/**
* 求深度
* @param node
* @param level
* @return
*/
public static int mostLeftLevel(Node node, int level) {
while (node != null) {
level++;
node = node.left;
}
return level - 1;
}