最大深度
-
题目:Leetcode104,559
-
思路:
-
递归:可以使用前序遍历求深度(中左右),也可以使用后序遍历求高度(左右中)。根节点的高度就是二叉树的最大深度。
-
//104.二叉树的最大深度
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);
}
};
//559.n叉树的最大深度
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> children;
Node() {}
Node(int _val) {
val = _val;
}
Node(int _val, vector<Node*> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public:
int maxDepth(Node* root) {
if(root == NULL) return 0;
int depth = 0;
for(int i = 0; i < root->children.size(); i++) {
depth = max(depth, maxDepth(root->children[i]));
}
return depth + 1;
}
};
最小深度
- 题目:Leetcode111
- 思路:可以使用前序遍历求深度,也可以使用后序遍历求高度。使用后序遍历,其实求的是根节点到叶子节点的最小距离,就是求高度的过程,不过这个最小距离 也同样是最小深度。
- 注意误区:最小深度是从根节点到最近叶子节点的最短路径上的节点数量!!!叶子节点!!!左右孩子都为空的节点才是叶子节点。
- 求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。
//超出时间限制
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 && node->right) return 1 + getDepth(node->right);
//左孩子不为空,右孩子为空
if(node->left && !node->right) return 1 + getDepth(node->left);
//左右孩子都不为空,取高度小的
int depth = 1 + min(leftDepth, rightDepth);
return depth;
}
int minDepth(TreeNode* root) {
return getDepth(root);
}
};
完全二叉树的节点个数
- 题目:Leetcode222
- 思路:
- 按普通二叉树来处理:递归法与求二叉树深度类似,迭代法由层序遍历的模板做修改,记录遍历的节点数量。
- 完全二叉树:分析完全二叉树的情况,一种是满二叉树,可以直接用 2^树深度 - 1 来计算(根节点深度为1);一种是最后一层叶子节点没有满,此时分别递归左孩子和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照慢二叉树来计算。
- 如何判断一个子树是不是满二叉树?
- 在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。判断其子树是不是满二叉树,如果是则利用公式计算这个子树(满二叉树)的节点数量,如果不是则继续递归。
//普通二叉树:递归
class Solution {
public:
int getNodesNum(TreeNode* node) {
if(node == NULL) return 0;
int leftNum = getNodesNum(node->left);
int rightNum = getNodesNum(node->right);
int sum = leftNum + rightNum + 1;
return sum;
}
int countNodes(TreeNode* root) {
return getNodesNum(root);
}
};
//时间复杂度:O(n)
//空间复杂度:O(log n),算上了递归系统栈占用的空间
//普通二叉树:迭代
class Solution {
public:
int countNodes(TreeNode* root) {
queue<TreeNode*> que;
if(root != NULL) que.push(root);
int res = 0;
while(!que.empty()) {
int size = que.size();
while(size--) {
TreeNode* node = que.front();
que.pop();
res++;
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return res;
}
};
//时间复杂度:O(n)
//空间复杂度:O(n)
//完全二叉树:递归
class Solution {
public:
int countNodes(TreeNode* root) {
if(root == nullptr) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int lDepth = 0, rDepth = 0;//初始化为0,方便后续求数
while(left) { //求左子树深度
left = left->left;
lDepth++;
}
while(right) { //求右子树深度
right = right->right;
rDepth++;
}
//当为满二叉树时,求节点数
if(lDepth == rDepth) return (2 << lDepth) - 1;//(2<<1) 相当于2^2,所以leftDepth初始为0
int leftCount = countNodes(root->left);
int rightCount = countNodes(root->right);
int sum = leftCount + rightCount + 1;
return sum;
}
};
//时间复杂度:O(log n × log n)
//空间复杂度:O(log n)
总结
辨析深度与高度的区别以及用哪种遍历来计算
参考链接
代码随想录:最大深度 最小深度 完全二叉树的节点个数