完全二叉树的节点个数
题目描述
力扣链接🔗

代码解析
以普通二叉树的思路来求
递归遍历
参考二叉树深度递归遍历的思想,可以使用二叉树递归遍历模板。
二叉树深度需要比较的是左右孩子的深度最大值,而此时求得是节点数,所以左右孩子 + 1(当前节点)即为此节点得节点数。
/*** 递归法** @param root* @return*/public int countNodes(TreeNode root) {return reverse(root);}public int reverse(TreeNode root) {if (root == null) { // 当为空时,表示没有节点,返回0return 0;}int leftNum = reverse(root.left); // 计算左孩子的节点数int rightNum = reverse(root.right); // 计算右孩子的节点数return leftNum + rightNum + 1; // 左节点数 + 右节点数 + 中间节点}// 后序遍历简洁版(类似求深度时的求高度遍历)public int countNodes(TreeNode root) {if (root == null) return 0;return 1 + countNodes(root.left) + countNodes(root.right);}
- 时间复杂度:
#card=math&code=O%28n%29&id=ITk8w)
 - 空间复杂度:
#card=math&code=O%28%5Clog%20n%29&id=bT26H),算上了递归系统栈占用的空间
 
迭代遍历
层序迭代遍历模板修改即可。
/*** 层序遍历* @param root* @return*/public int countNodes(TreeNode root) {if (root == null) {return 0;}Queue<TreeNode> queue = new LinkedList<>();queue.offer(root);int num = 0;while (!queue.isEmpty()) {int len = queue.size();while (len > 0) {TreeNode node = queue.poll();if (node.left != null) queue.offer(node.left);if (node.right != null) queue.offer(node.right);num++; // 节点个数加一len--;}}return num;}
- 时间复杂度:
#card=math&code=O%28n%29&id=JFWO8)
 - 空间复杂度:
#card=math&code=O%28n%29&id=AFR87)
 
完全二叉树思想
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。


如果整个树不是满二叉树,则递归整个树来求节点数,如果为满二叉树,使用满二叉树得公式求节点即可。
/*** 完全二叉树的性质** @param root* @return*/public int countNodes(TreeNode root) {if (root == null) {return 0;}TreeNode leftNode = root.left;TreeNode rightNode = root.right;int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便// 求左孩子的深度while (leftNode != null) {leftNode = leftNode.left;leftDepth++;}// 求右孩子的深度while (rightNode != null) {rightNode = rightNode.right;rightDepth++;}if (leftDepth == rightDepth) { // 此时为满二叉树return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftHeight初始为0}// 不为满二叉树则继续递归,注意加上自身节点return countNodes(root.left) + countNodes(root.right) + 1;}
- 时间复杂度:
#card=math&code=O%28%5Clog%20n%20%C3%97%20%5Clog%20n%29&id=hkNdP)
 - 空间复杂度:
#card=math&code=O%28%5Clog%20n%29&id=sJLpF)
 
// 求左孩子的深度while (leftNode != null) {leftNode = leftNode.left;leftDepth++;}// 求右孩子的深度while (rightNode != null) {rightNode = rightNode.right;rightDepth++;}
这段代码就是来判断是否为满二叉树,最左边深度和最右边的深度进行比较,根据满二叉树的性质。
