目录
题目链接:104.二叉树的最大深度
思路一:后序遍历,递归写法
最大深度是根节点到最远的叶子节点的距离。最大深度和根节点的最大高度是相等的,因此这道题可以求根节点最大高度。使用后序遍历,左右中,先获取孩子节点的高度,返回给父节点,逐层向上,最后得到最大高度。
代码
class Solution {
public:
int maxheight(TreeNode* root) {
if (root == NULL)
return 0; // 空节点的高度为0
// 后序遍历,左右中
int left = maxheight(root->left); // 左
int right = maxheight(root->right); // 右
// 当前节点为父节点,left和right都是子节点的高度
// 因此父节点的高度要加1
int maxh = 1 + max(left, right); // 中
return maxh;
}
int maxDepth(TreeNode* root) {
// 根节点的最大高度等于该树的最大深度
return maxheight(root);
}
};
思路二:层序遍历,迭代写法
采用层序遍历,一层一层的遍历二叉树,每一层深度加1,采用队列来做。
代码
class Solution {
public:
int maxDepth(TreeNode* root) {
queue<TreeNode*> que;
if (root == NULL)
return 0;
que.push(root);
int depth = 0;
while (!que.empty()) {
int size = que.size(); // 记录该层元素个数
depth++;
while (size--) {
TreeNode* node = que.front();
que.pop();
if (node->left)
que.push(node->left);
if (node->right)
que.push(node->right);
};
}
return depth;
}
};
题目链接:559. N 叉树的最大深度
思路一:后序遍历,递归写法
与104.二叉树的最大深度思路一样.
代码
class Solution {
public:
int maxheight(Node* root) {
if (root == NULL)
return 0;
int height = 0;
for (int i = 0; i < root->children.size(); i++) {
height = max(height, maxheight(root->children[i]));
}
return height + 1;
}
int maxDepth(Node* root) { return maxheight(root); }
};
思路二:层序遍历,迭代写法
与上相同。
代码
class Solution {
public:
int maxDepth(Node* root) {
queue<Node*> que;
if (root == NULL)
return 0;
que.push(root);
int depth = 0;
while (!que.empty()) {
int size = que.size();
depth++;
while (size--) {
Node* node = que.front();
que.pop();
for (int i = 0; i < node->children.size(); i++) {
que.push(node->children[i]);
}
}
}
return depth;
}
};
题目链接:111.二叉树的最小深度
思路一:后序遍历,递归写法
与求最大深度类似,采用后序遍历将子节点的深度返回给父节点,逐层往上,最后求最小值即可。不同的是需要单独判断其中一个子树为空的情况,这时要返回的是另一子树的最小深度。不然就会出现将空节点NULL当作0向上传的情况。
代码
class Solution {
public:
int minheight(TreeNode* root) {
if (root == NULL)
return 0;
int lefth = minheight(root->left);
int rigthh = minheight(root->right);
if (root->left == NULL && root->right != NULL) {
return 1 + rigthh;
}
if (root->left != NULL && root->right == NULL) {
return 1 + lefth;
}
return 1 + min(lefth, rigthh);
}
int minDepth(TreeNode* root) { return minheight(root); }
};
思路二:层序遍历,迭代写法
与前两题的层序遍历思路相同。有区别的地方在于从上往下遍历,如果遇到某一节点的左右孩子都为空,则返回该层深度,此时的深度就是最小深度。
代码
class Solution {
public:
int minDepth(TreeNode* root) {
queue<TreeNode*> que;
if (root == NULL)
return 0;
que.push(root);
int depth = 0;
while (!que.empty()) {
int size = que.size();
depth++;
while (size--) {
TreeNode* node = que.front();
que.pop();
if (node->left == NULL && node->right == NULL) {
return depth;
}
if (node->left)
que.push(node->left);
if (node->right)
que.push(node->right);
}
}
return depth;
}
};
题目链接:222.完全二叉树的节点个数
思路一:后序遍历,递归写法
该题求的是完全二叉树的节点个数,利用完全二叉树的特性,除了最后一层节点可能不满,其他层的节点都是满的,也就是说完全二叉树可以由若干个满二叉树组合构成。递归时,判断左右子树是否是满二叉树,在这道题向左和向右遍历的深度一样即为满二叉树。
满二叉树节点数量等于2^深度-1
代码
class Solution {
public:
int getnum(TreeNode* root) {
if (root == NULL)
return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftdepth = 0;
int rightdepth = 0;
// 判断左右子树是否为满二叉树
while (left) {
left = left->left;
leftdepth++;
}
while (right) {
right = right->right;
rightdepth++;
}
if (leftdepth == rightdepth) {
return (2 << leftdepth) - 1;
}
// 后序遍历
int leftnum = getnum(root->left); // 左
int rightnum = getnum(root->right); // 右
int result = leftnum + rightnum + 1; // 中
return result;
}
int countNodes(TreeNode* root) { return getnum(root); }
};
思路二:层序遍历,迭代写法
按层遍历二叉树,累加节点个数即可。
代码
class Solution {
public:
int countNodes(TreeNode* root) {
queue<TreeNode*> que;
if (root == NULL)
return 0;
que.push(root);
int count = 0;
while (!que.empty()) {
int size = que.size();
while (size--) {
count++;
TreeNode* node = que.front();
que.pop();
if (node->left)
que.push(node->left);
if (node->right)
que.push(node->right);
}
}
return count;
}
};
总结
①目前来看,二叉树的相关题目最关键的地方在于遍历的方式,无论对二叉树做何种操作,都需要遍历到想要的节点
②递归法的前中后序遍历代码相对简洁,但是逻辑一定要搞清楚,尤其是应该选择哪一种遍历方法
③104.二叉树的最大深度和111.二叉树的最小深度这两道题,昨天使用层序遍历解决,今天学习了如何使用后序遍历递归解决