104.二叉树的最大深度
这道题目考查的点是深度,最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。求深度需要前序遍历,但是我们可以进行转换,一个树的最大深度等于最大高度,深度是自上而下,高度是自下而上,求高度可以用后序,实现起来更容易,对应递归三要素:
1. 参数:只需要访问的树节点,返回类型就是所求的高度/深度;
2. 结束条件:当节点是nullptr时候,说明已经访问到叶子节点的下一层,此时的高度是0。
3. 单层处理逻辑:用后序遍历,先得到左节点的最大深度,再得到右节点的最大深度,则当前节点的最大深度就是1+二者中的较大者。
代码如下:
class Solution {
public:
int maxDepth(TreeNode* root) {
//等效为求高度 后序遍历
if(root==nullptr) return 0;
int left = maxDepth(root->left); //左
int right = maxDepth(root->right); //右
return 1+max(left,right);
}
};
这道题目也可以用层序遍历的思路来做,遍历到最后一层,就是其最大深度,层序遍历固定模板,代码如下:
class Solution {
public:
int maxDepth(TreeNode* root) {
//层序遍历
int depth=0;
if(root==nullptr) return 0;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
int len = q.size();
depth++;
for(int i=0;i<len;i++){
TreeNode* node = q.front();
q.pop();
if(node->left) q.push(node->left);
if(node->right) q.push(node->right);
}
}
return depth;
}
};
拓展:顺便完成N叉树的最大深度
代码如下:
class Solution {
public:
int maxDepth(Node* root) {
if(root==nullptr) return 0;
int dep=0;
for(Node* chlid:root->children)
{
dep=max(dep,maxDepth(chlid));
}
return dep+1;
}
};
111.二叉树的最小深度
这道题和最大深度思路类似,但是有陷阱,需要注意最小深度是从根节点到最近叶子节点的最短路径上的节点数量。因此如果一个节点没有节点,只有右节点,该节点的最小深度应该是1+右节点的最小深度,因为最小深度的定义是到最近叶子节点,该节点不是叶子节点,不满足要求。
代码如下:
class Solution {
public:
int minDepth(TreeNode* root) {
//高度-后序遍历
if(root==nullptr) return 0;
int left=minDepth(root->left);
int right=minDepth(root->right);
if(root->left==nullptr&&root->right!=nullptr) return 1+right;
else if(root->left!=nullptr&&root->right==nullptr) return 1+left;
else return 1+min(left,right);
}
};
222.完全二叉树的节点个数
这道题目看到时候,只想到用后序遍历,当作一个普通的二叉树返回其节点个数,代码如下:
class Solution {
public:
int countNodes(TreeNode* root) {
if(root==nullptr) return 0;
int left=countNodes(root->left);
int right = countNodes(root->right);
return left+right+1;
}
};
学习代码随想录后,总结其思路如下:
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
如果整个树不是满二叉树,就递归其左右孩子,直到遇到满二叉树为止,用公式计算这个子树(满二叉树)的节点数量。
这里关键在于如何去判断一个左子树或者右子树是不是满二叉树呢?
在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。这种思路可以不用遍历每一个节点,有效的减少复杂度。
代码如下:
class Solution {
public:
int countNodes(TreeNode* root) {
//结束条件
if(root==nullptr) return 0;
int leftd=0, rightd=0;
TreeNode* left=root->left;
TreeNode* right=root->right;
while(left)
{
left=left->left;//左侧深度
leftd++;
}
while(right)
{
right=right->right; //右侧深度
rightd++;
}
if(leftd==rightd) return (2<<leftd)-1; //2的n次方-1
//处理每层逻辑
int l=countNodes(root->left);//左
int r=countNodes(root->right);
return 1+l+r;
}
};