104.二叉树的最大深度
深度:是二叉树里面任意一个节点到根节点的距离。
有的规则是 根节点的深度为1 有的为0 ,但需要统一规则,其他节点的深度就在根节点的深度上累加
- 求深度应该是前序遍历 中左右
- 往下遍历一个,加一
高度:是二叉树中任意一个节点到叶子节点的距离
- 求高度应该是后序遍历 左右中
- 求高度是从下往上计数,叶子节点是1,后序遍历:将子节点的高度返回给父节点,父节点再加一
- 父节点高度=左右孩子节点高度最大值 + 1,也就是返回值,递归部分就是去求左孩子和右孩子的高度。
根节点的高度 就是 二叉树的最大深度
所以两种遍历方式对于本题均可进行求解,本题目前使用的是后序遍历,前序遍历要比后序遍历麻烦一些
后序遍历会持续递归到最下面的一棵子树,写代码的时候不要看整棵树,按照最下面那棵子树的结构来写就行。这也就是对应了 递归三要素中的第三要素:单层逻辑。
class Solution {
public:
int maxDepth(TreeNode* root) {
return getHeight(root);
}
int getHeight(TreeNode* node) {
if (node == NULL) return 0;
int leftHeight = getHeight(node->left);
int rightHeight = getHeight(node->right);
int height = 1 + (leftHeight > rightHeight ? leftHeight : rightHeight);
return height;
}
};
559.n叉树的最大深度
整体思路 与求 二叉树最大深度思路一致,只不过在递归第三要素-单层逻辑的时候,需要改下。
class Solution {
public:
int maxDepth(Node* root) {
return getDepth(root);
}
int getDepth(Node* node) {
if (node == NULL) return 0;
int depth = 0;
for (int i = 0; i < node->children.size(); i++) {
int tmpDepth = getDepth(node->children[i]);
if (depth < tmpDepth) {
depth = tmpDepth;
}
}
return depth + 1;
}
};
111.二叉树的最小深度
- 该题目使用后序遍历是可以的,把后序的 左右中 的 中 改为最小的然后加1
- 这道题目的思路更适合用前序遍历,
- 最小深度和最大深度 两者用 后序遍历和前序遍历应该都行,只不过前序遍历的代码要稍微麻烦一些
- 注意:需要避免一个陷阱,当左子树为空时,此时是返回的右子树的深度,而不是两者最小的深度, 只有当左右子树均不为空时,才是返回两者的最小深度。
class Solution {
public:
int minDepth(TreeNode* root) {
return getHeight(root);
}
int getHeight(TreeNode* node) {
if (node == NULL) return 0;
int leftHeight = getHeight(node->left);
int rightHeight = getHeight(node->right);
if (node->left == NULL && node->right != NULL) return 1 + rightHeight;
if (node->left != NULL && node->right == NULL) return 1 + leftHeight;
int height = 1 + (leftHeight < rightHeight ? leftHeight : rightHeight);
return height;
}
};
222.完全二叉树的节点个数
- 可以利用后序遍历来写,后序遍历相较于其他两种遍历代码是最简洁的,时间复杂度O(n)
- 也可以利用完全二叉树的思路来做,就是去判断一个节点的左孩子的最左深度与右孩子的最右深度是否相等,若相等,则该节点对应的子树的为满二叉树,直接利用满二叉树的公式,根据层数计算节点的个数:2的n次方 - 1;虽然复杂度也为O(n),但是若为满二叉树,则中间的节点就不需要遍历了。
- 终止条件:除了节点为null;还有 当子树为满二叉树的时候,也需要返回上去
后序遍历
class Solution {
public:
// 利用后序遍历的顺序
int countNodes(TreeNode* root) {
return getNum(root);
}
int getNum (TreeNode* node) {
if (node == NULL) return 0;
int leftNum = getNum(node->left);
int rightNum = getNum(node->right);
int Num = 1 + leftNum + rightNum;
return Num;
}
};
基于完全二叉树特性
class Solution {
public:
// 利用完全二叉树法
int countNodes(TreeNode* root) {
return getCnt(root);
}
int getCnt (TreeNode* node) {
if (node == NULL) return 0;
int leftDepth = 0; // 这里将深度初始化为0 是有目的的,是基于编程语言特性
int rightDepth = 0;
TreeNode* left = node->left;
TreeNode* right = node->right;
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
int leftCnt = getCnt (node->left);
int rightCnt = getCnt (node->right);
return leftCnt + rightCnt + 1;
}
};