题目描述
已知一棵完全二叉树,求其节点的个数
要求:时间复杂度低于O(N),N为这棵树的节点个数
实现思路
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
首先判断根节点的右子树的左边界。
- 左子树的左边界在最后一层。
- 说明此时根的左子树为满二叉树
- 所有节点数 = 左子树 + 根节点 + 右子树
左子树为满二叉树,高度为lH=H-1。那么左子树的节点个数为(1 << lH) - 1也就是2的lH次方减一。
2. 右子树的左边界没到最后一层
- 右子树为满二叉树,但是高度比左子树小1
- 所有节点数 = 右子树 + 根节点 + 左子树
如何计算:
情况1的时候,左子树为满二叉树,左子树节点为(1 << 左子树高度) - 1,加上根节点1,右子树此时为满二叉树。
所有节点数 = (1 << 左子树高度) + 右子树节点数(递归计算)
情况2的时候,同理。
public class CompleteTreeNodeNumber {
public static class Node {
int val;
Node left;
Node right;
public Node(int data) {
this.val = data;
}
}
public static int nodeNum(Node head) {
if (head == null) return 0;
return bs(head, 1, heightOfTree(head, 1));
}
/**
* @param node 当前节点
* @param level 层次
* @param h 整棵树的高度
* @return 树的所有节点数量
*/
public static int bs(Node node, int level, int h) {
if (level == h) {
return 1;
}
if (heightOfTree(node.right, level + 1) == h) {
return (1 << (h - level)) + bs(node.right, level + 1, h);
} else {
return (1 << (h - level - 1) + bs(node.left, level + 1, h));
}
}
private static int heightOfTree(Node head, int level) {
while (head != null) {
level++;
head = head.left;
}
return level - 1;
}
}