给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
提示:
- 树中节点的数目范围是
[0, 5 * 104]
0 <= Node.val <= 5 * 104
- 题目数据保证输入的树是 完全二叉树
解题思路:这个题解题思路可以分为两种:①不利用完全二叉树的性质,当作正常二叉树求节点个数的方法来进行。②利用完全二叉树的性质来进行求解。
直接求解:
递归法:利用后序遍历,在后序遍历的过程中统计结点的个数,代码如下:
class Solution {
//普通二叉树的做法:后序遍历的递归
public int countNodes(TreeNode root) {
if(root == null){
return 0 ;
}
return getNum(root);
}
public int getNum(TreeNode root){
if(root == null){
return 0 ;
}
int left = getNum(root.left);
int right = getNum(root.right);
return left + right + 1;
}
}
迭代法:利用前序遍历的迭代写法,在迭代的过程中统计节点的个数,代码如下:
class Solution{
//普通二叉树的做法:迭代的前序遍历
public int countNodes(TreeNode root) {
if(root == null){
return 0 ;
}
int count = 0;
Stack<TreeNode> stack = new Stack();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
count++;
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return count;
}
}
迭代法:利用层序遍历的迭代写法,在迭代的过程中统计节点的个数,代码如下:
//普通二叉树:层序遍历的办法
public int countNodes(TreeNode root) {
if(root == null){
return 0 ;
}
int count = 0;
Queue<TreeNode> queue = new LinkedList();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.remove();
count++;
if(node.left != null){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
return count;
}
利用完全二叉树的性质:
以上方法都是按照普通二叉树来做的。
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
代码如下:
class Solution{
//完全二叉树的做法:后序遍历递归
public int countNodes(TreeNode root) {
return getNum(root);
}
public int getNum(TreeNode root){
if(root == null){
return 0 ;
}
TreeNode left = root.left;
TreeNode right = root.right;
int leftNum = 0;
int rightNum = 0;
while(left != null){
left = left.left;
leftNum++;
}
while(right != null){
right = right.right;
rightNum++;
}
if(leftNum == rightNum){
return (2 << leftNum) - 1;
}
return getNum(root.left) + getNum(root.right) + 1;
}
}