104.二叉树的最大深度
力扣题目链接
题目描述:
给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:3
示例 2:
输入:root = [1,null,2]
输出:2
思路:
- 递归法:采用后序遍历,分别求左子树和右子树的深度,取最大值即可。递归三部曲如下:
- 确定参数和返回值:参数是根节点,返回值为深度int即可
- 函数退出条件:当节点为空,return 0;
- 单步处理逻辑:分别递归左节点和右节点,然后取它们返回值的最大值 + 1。
代码实现:
int maxDepth(TreeNode* root) {
if (root == nullptr) return 0;
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return (left > right ? left : right) + 1;
}
- 迭代法:采用层次遍历,遍历到每层的时候depth+1,最终得到层数
int maxDepth(TreeNode* root) {
if(root == nullptr) return 0;
queue<TreeNode*> que;
que.push(root);
int depth = 0;
int size = 0;
while(!que.empty()) {
size = que.size();
depth++;
for(int i = 0 ; i < size; ++i) {
TreeNode* cur = que.front();
que.pop();
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
}
return depth;
}
111.二叉树的最小深度
力扣题目链接
题目描述:
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:2
示例 2:
输入:root = [2,null,3,null,4,null,5,null,6]
输出:5
思路:
- 递归法: 这道题和求最大深度类似,但是注意这里有个误区就是,它不是取左右子树的高度最小值,如果遇到左子树空右子树不空这种情况返回的是0,而此时右子树递归返回的是非0,两者取最小值最终返回的是0,这肯定不对。所以需要修改,在左子树为空右子树非空时,用右子树最小深度,而反之亦然,都为空(都为空时,递归两个子树得到的结果都是0)或者都不为空的时候取两个子树最小深度即可,递归三部曲如下:
- 函数参数和返回值:参数为根节点、返回值为最小深度
- 退出条件:当节点为空的时候return 0;
- 单步处理逻辑:左子树为空右子树非空,
return left_depth + 1;
右子树为空,左子树非空,return right_depth + 1;
都为空或者都不为空return min(left_depth, right_depth) + 1;
代码实现:
int minDepth(TreeNode* root) {
if (root == nullptr) return 0;
int left_depth = minDepth(root->left);
int right_depth = minDepth(root->right);
if (root->left && !root->right) {
return left_depth + 1;
} else if (!root->left && root->right) {
return right_depth + 1;
}
return min(left_depth, right_depth) + 1;
}
- 迭代法:采用层次遍历,遍历每层时遇到叶子节点退出即可(左右子树都为空的时候)
代码实现:
int minDepth(TreeNode* root) {
if (root == nullptr) return 0;
queue<TreeNode*> que;
que.push(root);
int size = 0, depth = 0;
while(!que.empty()) {
size = que.size();
depth++;
for (int i = 0; i < size; ++i) {
TreeNode* cur = que.front();
que.pop();
if (!cur->left && !cur->right) {
return depth;
}
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
}
return depth;
}
222.完全二叉树的节点个数
力扣题目链接
题目描述:
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 2^(h -1) 个节点。
思路:
- 方法一:按照普通二叉树来做的话,递归法就是分别求左右子树的节点数量,然后求和+1即可。而迭代法就是层次遍历(前中后序后可以),然后求节点个数。
代码实现:
//递归法
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
int left_count = countNodes(root->left);
int right_count = countNodes(root->right);
return left_count + right_count + 1;
}
//迭代法
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
queue<TreeNode*> que;
que.push(root);
int size = 0, sum = 0;
while(!que.empty()) {
size = que.size();
for (int i = 0; i < size; ++i) {
TreeNode* cur = que.front();
que.pop();
sum++;
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
}
return sum;
}
- 方法二:利用完全二叉树的性质做题,完全二叉树的子树也是完全二叉树,然后我们去判断它是不是满二叉树,如果是满二叉树直接利用公式计算,否则就递归判断子树。
- 递归三部曲:
- 确定函数参数和返回值:函数参数为根节点和,返回值为int类型
- 退出条件:根节点为空时,return 0;
- 单步逻辑:先判断是不是满二叉树,如果是满二叉树直接求节点数就行,不是满二叉树交给递归。
- 如何判断满二叉树?
- 由于题目已经给出输入的一定是完全二叉树,那么我们沿着左子树一直往左找,直到left指针为空,这个节点一定是叶子节点,而右子树一样的道理,然后求出左子树和右子树的深度,如果深度相等就是满二叉树。
代码实现:
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
int left_depth = 0, right_depth = 0;
TreeNode* cur = root->left;
while(cur) {
left_depth++;
cur = cur->left;
}
cur = root->right;
while(cur) {
right_depth++;
cur = cur->right;
}
if (left_depth == right_depth) {
return (2 << left_depth) - 1; //这里是 2 *(2^h - 1)+ 1,化简后为 2^(h+1) -1,换为位运算就是(2<< h) - 1
} else{
return countNodes(root->left) + countNodes(root->right) + 1;
}
}