方法一:普通二叉树的求法
方法二:完全二叉树性质的求法
方法一:普通二叉树的求法
这道题目的递归法和求二叉树的深度写法类似, 而迭代法,遍历模板稍稍修改一下,记录遍历的节点数量就可以了。
递归遍历的顺序依然是后序(左右中)。三部曲前两部暂时省略
最后一步:确定单层递归的逻辑:先求它的左子树的节点数量,再求右子树的节点数量,最后取总和再加一 (加1是因为算上当前中间节点)就是目前节点为根节点的节点数量。
- 时间复杂度:O(n)
- 空间复杂度:O(log n),算上了递归系统栈占用的空间
迭代法:
- 时间复杂度:O(n)
- 空间复杂度:O(n)
方法二:完全二叉树性质的求法
完全二叉树中必包含满二叉树。先理解完全二叉树的定义:
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
关键在于如何去判断一个左子树或者右子树是不是满二叉树呢?
在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。
判断其子树是不是满二叉树,如果是则利用公式计算这个子树(满二叉树)的节点数量,如果不是则继续递归,那么 在递归三部曲中,第二部:终止条件的写法应该是这样的:
有两个终止条件:第一个是判断是否为空,第二个是判断是否为满二叉树。
if (root == null) return 0;
TreeNode left = root.left;
TreeNode right = root.right;
int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
while (left != null) { // 求左子树深度
left = left.left;
leftDepth++;
}
while (right != null) { // 求右子树深度
right = right.right;
rightDepth++;
}
if (leftDepth == rightDepth) {
return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
}
- 时间复杂度:O(log n × log n)
- 空间复杂度:O(log n)