完全二叉树的节点个数
如果只是求一个二叉树的节点个数,是相对来说比较容易的,无论是递归法还是迭代法,都可以很容易的想出思路,此处我直接贴出代码
普通二叉树
递归
class Solution { // 通用递归解法 public int countNodes(TreeNode root) { if(root == null) { return 0; } return countNodes(root.left) + countNodes(root.right) + 1; } }
迭代
class Solution { // 迭代法 public int countNodes(TreeNode root) { if (root == null) return 0; Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); int result = 0; while (!queue.isEmpty()) { int size = queue.size(); while (size -- > 0) { TreeNode cur = queue.poll(); result++; if (cur.left != null) queue.offer(cur.left); if (cur.right != null) queue.offer(cur.right); } } return result; } }
完全二叉树
既然本题要求的是完全二叉树,所以就要利用完全二叉树的特点。
完全二叉树我们都不陌生,按照通俗的话来讲,就是:满二叉树 或者 只缺右下角节点的满二叉树
所以我们就分两种情况来判断
-
满二叉树的情况
满二叉树的节点个数只和树的层高(深度)有关:2的n次方-1(如图所示,节点个数为2的4次方-1 = 15)
-
只缺右下角节点的满二叉树
可以把这种情况的的完全二叉树拆分成两个完全二叉树,再对两个二叉树分别做判断,如果不是满二叉树就继续拆,一直拆到是满二叉树为止
以此完全二叉树为例,根节点的左子树为满二叉树,可以直接得出节点个数,右子树为完全二叉树,可以再将右子树作为根节点进一步进行细分(递归)
我们发现左子树为满二叉树,右子树为完全二叉树。以此类推。
那我们怎么判断该树是否是完全二叉树还是满二叉树呢
可以用左右子树的深度来判断
但是左右子树的深度不用像之前递归一样把每个节点都遍历一遍。依据完全二叉树的性质,我们只用看整个树的最左下角节点和右下角节点的深度就可以了。
以上图只缺右下角节点的满二叉树为例
其左下角的节点为8,右下角的节点为7。
其深度用简单的循环就可以求出
while(left != null) { left = left.left; leftDepth++; }
同理求出最右下角节点。
只用比较这两个节点的深度是否相等即可:leftDepth == rightDepth
代码
class Solution { public int countNodes(TreeNode root) { //利用完全二叉树的特点 if (root == null) return 0; TreeNode left = root.left; TreeNode right = root.right; int leftDepth = 0;//leftDepth+1表示当前的层数,方便后面计算 int rightDepth = 0; while (left != null) { left = left.left; leftDepth++; } while (right != null) { right = right.right; rightDepth++; } if (leftDepth == rightDepth) { // return (int) (Math.pow(2,leftDepth+1) - 1); return (2 << leftDepth) - 1;//前面让leftDepth从0开始就是为了方便这里的计算,本行和上一行等价 } return countNodes(root.left) + countNodes(root.right) + 1; } }