⭐高度👆 vs 深度👇:

- 二叉树节点的高度👆(后序):指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从1开始)
- 二叉树节点的深度👇(前序):指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
视频讲解
https://www.bilibili.com/video/BV1Gd4y1V75u/?vd_source=f98f2942b3c4cafea8907a325fc56a48文章讲解
https://programmercarl.com/0104.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%A4%A7%E6%B7%B1%E5%BA%A6.html
根节点的高度就是二叉树的最大深度
- 思路:
- 通过后序求根节点的高度:(父节点高度 = 子节点高度 + 1)
- 确定递归函数的参数和返回值:根节点 int
- 确定终止条件:如果为空节点的话,就返回0,表示高度为0。
- 确定单层递归的逻辑:先求它的左子树的高度,再求右子树的高度,最后左右子树高度取大 再+1 (加1是因为算上当前中间节点)就是当前子树的高度。
- 通过前序求根节点的深度:(子节点深度 = 父节点深度 + 1)
- 确定递归函数的参数和返回值:(Treenode* node, int depth) void
- 确定终止条件:如果为叶子节点的话,就返回。
- 确定单层递归的逻辑:左孩子非空,则求左孩子深度;右孩子非空,则求右孩子深度。父节点深度为 depth,故 depth + 1 就是当前节点的深度。
- 代码:
// 后序
class solution {
public:
int getdepth(Treenode* node) {
if (node == NULL) return 0;
int leftdepth = getdepth(node->left); // 左
int rightdepth = getdepth(node->right); // 右
int depth = 1 + max(leftdepth, rightdepth); // 中
return depth;
}
int maxdepth(Treenode* root) {
return getdepth(root);
}
};
// 后序:精简版
class solution {
public:
int maxdepth(Treenode* root) {
if (root == null) return 0;
return 1 + max(maxdepth(root->left), maxdepth(root->right));
}
};
// 前序
class solution {
public:
int result;
void getdepth(Treenode* node, int depth) {
result = depth > result ? depth : result; // 中
if (node->left == NULL && node->right == NULL) return ;
if (node->left) { // 左
depth++; // 深度+1
getdepth(node->left, depth);
depth--; // 回溯,深度-1
}
if (node->right) { // 右
depth++; // 深度+1
getdepth(node->right, depth);
depth--; // 回溯,深度-1
}
return ;
}
int maxdepth(Treenode* root) {
result = 0;
if (root == NULL) return result;
getdepth(root, 1);
return result;
}
};
// 前序:精简版
class solution {
public:
int result;
// node为当前处理节点(非空),depth为node的深度
void getdepth(Treenode* node, int depth) {
result = depth > result ? depth : result; // 中
if (node->left == NULL && node->right == NULL) return ;
if (node->left) { // 左
getdepth(node->left, depth + 1);
}
if (node->right) { // 右
getdepth(node->right, depth + 1);
}
return ;
}
int maxdepth(Treenode* root) {
result = 0;
if (root == 0) return result;
// 根节点(非空)深度为1
getdepth(root, 1);
return result;
}
};
// 迭代:层序
class solution {
public:
int maxdepth(Treenode* root) {
if (root == NULL) return 0;
int depth = 0;
queue<Treenode*> que;
que.push(root);
while(!que.empty()) {
int size = que.size();
depth++; // 记录深度
for (int i = 0; i < size; i++) {
Treenode* node = que.front();
que.pop();
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return depth;
}
};
相关题目:
// 递归法(后序)
class solution {
public:
int maxdepth(node* root) {
if (root == 0) return 0;
int depth = 0;
for (int i = 0; i < root->children.size(); i++) {
depth = max (depth, maxdepth(root->children[i]));
}
return depth + 1;
}
};
// 前序
class Solution {
public:
int result;
// depth为node父节点的深度
void getHeight(Node* node, int depth) {
if (node == NULL) return;
// node深度:depth + 1
result = (depth + 1) > result ? (depth + 1) : result;
for (int i = 0; i < node->children.size(); ++i) {
getHeight(node->children[i], depth + 1);
}
}
int maxDepth(Node* root) {
result = 0;
getHeight(root, 0);
return result;
}
};
// 迭代法(层序)
class solution {
public:
int maxdepth(node* root) {
queue<node*> que;
if (root != NULL) que.push(root);
int depth = 0;
while (!que.empty()) {
int size = que.size();
depth++; // 记录深度
for (int i = 0; i < size; i++) {
node* node = que.front();
que.pop();
for (int j = 0; j < node->children.size(); j++) {
if (node->children[j]) que.push(node->children[j]);
}
}
}
return depth;
}
};
最小深度是从根节点到最近叶子节点的最短路径上的节点数量
视频讲解
https://www.bilibili.com/video/BV1QD4y1B7e2文章讲解
https://programmercarl.com/0111.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E6%B7%B1%E5%BA%A6.html#%E9%80%92%E5%BD%92%E6%B3%95

- 思路:根节点到叶子节点的最小距离
- 后序:左右子树高度取小 → 以中节点为子树的最小深度?
- 递归函数参数、返回值:(Treenode* node) 返回值 int
- 确定终止条件:如果为空节点的话,就返回0,表示高度为0。
- 确定单层递归的逻辑:(若子树一空一非空,返回非空子树最小深度 +1)先求它的左子树的最小深度,再求右子树的最小深度,最后左右子树最小深度取小 再+1 (加1是因为算上当前中间节点)就是当前子树的最小深度。
- 前序:
- 确定递归函数的参数和返回值:(Treenode* node, int depth) void
- 确定终止条件:如果为叶子节点的话,记录结果,返回。
- 确定单层递归的逻辑:左孩子非空,则求左孩子最小深度;右孩子非空,则求右孩子最小深度。父节点深度为 depth,故 depth + 1 就是当前节点的深度。
- 代码:
// 后序
class Solution {
public:
int getDepth(TreeNode* node) {
if (node == NULL) return 0;
int leftDepth = getDepth(node->left); // 左
int rightDepth = getDepth(node->right); // 右
// 中
// 当一个左子树为空,右不为空,这时并不是最低点
if (node->left == NULL && node->right != NULL) {
return 1 + rightDepth;
}
// 当一个右子树为空,左不为空,这时并不是最低点
if (node->left != NULL && node->right == NULL) {
return 1 + leftDepth;
}
int result = 1 + min(leftDepth, rightDepth);
return result;
}
int minDepth(TreeNode* root) {
return getDepth(root);
}
};
// 后序:精简版
class Solution {
public:
int minDepth(TreeNode* root) {
if (root == NULL) return 0;
if (root->left == NULL && root->right != NULL) {
return 1 + minDepth(root->right);
}
if (root->left != NULL && root->right == NULL) {
return 1 + minDepth(root->left);
}
return 1 + min(minDepth(root->left), minDepth(root->right));
}
};
// 前序
class Solution {
private:
int result;
void getdepth(TreeNode* node, int depth) {
if (node->left == NULL && node->right == NULL) {
result = min(depth, result);
return;
}
// 中 只不过中没有处理的逻辑
if (node->left) { // 左
getdepth(node->left, depth + 1);
}
if (node->right) { // 右
getdepth(node->right, depth + 1);
}
return ;
}
public:
int minDepth(TreeNode* root) {
if (root == NULL) return 0;
result = INT_MAX;
getdepth(root, 1);
return result;
}
};
// 迭代:层序
class Solution {
public:
int minDepth(TreeNode* root) {
if (root == NULL) return 0;
int depth = 0;
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
int size = que.size();
depth++; // 记录最小深度
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
if (!node->left && !node->right) { // 当左右孩子都为空的时候,说明是最低点的一层了,退出
return depth;
}
}
}
return depth;
}
};
⭐完全二叉树:找满二叉树,利用公式计算节点个数:2^深度 - 1
视频讲解
https://www.bilibili.com/video/BV1eW4y1B7pD文章讲解
https://programmercarl.com/0222.%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E8%8A%82%E7%82%B9%E4%B8%AA%E6%95%B0.html
- 思路:
- 普通二叉树:左子树节点个数 + 右子树节点个数 + 1 时间复杂度:O(n)
- 完全二叉树:前序遍历找构成满二叉树的子树

前提:完全二叉树,每层从左到右节点连续,故可以直接判断两侧节点数,若相等则为满二叉树


- 参数、返回值:
- 终止条件:
if (root == nullptr) return 0; // 开始根据左深度和右深度是否相同来判断该子树是不是满二叉树 TreeNode* left = root->left; TreeNode* right = root->right; int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便 while (left) { // 求左子树深度 left = left->left; leftDepth++; } while (right) { // 求右子树深度 right = right->right; rightDepth++; } if (leftDepth == rightDepth) { return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,返回满足满二叉树的子树节点数量 } - 单层递归逻辑:左子树节点个数 + 右子树节点个数 + 1
- 代码:
// 适用于普通二叉树
// 递归
class Solution {
private:
int getNodesNum(TreeNode* cur) {
if (cur == NULL) return 0;
int leftNum = getNodesNum(cur->left); // 左
int rightNum = getNodesNum(cur->right); // 右
int treeNum = leftNum + rightNum + 1; // 中
return treeNum;
}
public:
int countNodes(TreeNode* root) {
return getNodesNum(root);
}
};
// 递归:精简版
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == NULL) return 0;
return 1 + countNodes(root->left) + countNodes(root->right);
}
};
// 迭代
class Solution {
public:
int countNodes(TreeNode* root) {
queue<TreeNode*> que;
if (root != NULL) que.push(root);
int result = 0;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
result++; // 记录节点数量
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
// 适用于完全二叉树
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
while (left) { // 求左子树深度
left = left->left;
leftDepth++;
}
while (right) { // 求右子树深度
right = right->right;
rightDepth++;
}
if (leftDepth == rightDepth) {
return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
}
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
注:2 << i - 1 2 左移 i - 1 位,相当于 2 * 2 * ... * 2 i - 1 个 2
即 2 ^ i
文章介绍了如何使用递归和迭代方法计算二叉树的最大深度和最小深度,包括后序和前序遍历的策略。同时,对于完全二叉树,文章提供了计算节点数量的方法,特别关注满二叉树的情况。

266

被折叠的 条评论
为什么被折叠?



