Leetcode 104.二叉树的最大深度
题目链接:104 二叉树的最大深度
题干:给定一个二叉树
root
,返回其最大深度。二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。
思考一:递归法,后序遍历形式。关键点:根节点的高度就是二叉树的最大深度。单层循环逻辑为 返回左右孩子节点的高度加一。
代码:
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == nullptr) return 0;
int left = maxDepth(root->left); //左
int right = maxDepth(root->right); //右
int depth = 1 + max(left, right); //中
return depth;
}
};
思考二:递归法,前序遍历形式。设置全局变量result,每次循环将当前节点的深度和记录值result比较,将较大记录到result中,并处理其非空孩子节点,当然注意函数回溯时要将深度减一。
代码:
class Solution {
public:
int result; //记录当前最大深度
void getMax(TreeNode* node, int depth) {
result = result > depth ? result : depth; //中
if (!node->left && !node->right) return; //叶子节点不用处理
if (node->left) //左
getMax(node->left, depth + 1);
if (node->right) //右
getMax(node->right, depth + 1);
return;
}
int maxDepth(TreeNode* root) {
result = 0;
if (!root) return result;
getMax(root, 1);
return result;
}
};
思考三:迭代法,昨天写过。
链接:第十五天| 二叉树的层序遍历、226.翻转二叉树、101. 对称二叉树
Leetcode 559.n叉树的最大深度
题目链接:559 n叉树的最大深度
题干: 给定一个 N 叉树,找到其最大深度。最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。N 叉树输入按层序遍历序列化表示,每组子节点由空值分隔。
思考一: 递归法,和二叉树唯一不同在处理多个孩子节点并比较,最后返回值加一(根节点)
代码:
class Solution {
public:
int maxDepth(Node* root) {
if (root == nullptr) return 0;
int depth = 0;
for (Node* node : root->children)
depth = max(depth, maxDepth(node));
return depth + 1;
}
};
思考二: 迭代法,和上题的迭代法差别只在将多个孩子节点入队
代码:
class Solution {
public:
int maxDepth(Node* root) {
queue<Node*> que;
int depth = 0;
if (root != nullptr) que.push(root);
while (!que.empty()) {
int size = que.size(); //记录每层节点个数
for (int i = 0; i < size; i++) {
Node* cur = que.front();
que.pop();
//将当前节点的所有非空孩子节点入队
for (int j = 0; j < cur->children.size(); j++)
if (cur->children[j]) que.push(cur->children[j]);
}
depth++;
}
return depth;
}
};
Leetcode 111.二叉树的最小深度
题目链接: 111 二叉树的最小深度
题干: 给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。叶子节点是指没有子节点的节点。
思考一: 递归法,后序遍历形式。
单层循环逻辑:
- 若只有左子树,则返回左子树的高度加一
- 若只有右子树,则返回右子树的高度加一
- 若左右子树均存在,则返回左右孩子节点的高度较小值加一
代码:
class Solution {
public:
int minDepth(TreeNode* root) {
if (!root) return 0;
int left = minDepth(root->left); //左
int right = minDepth(root->right); //右
if (root->left && !root->right) //左子树空则只计算右子树
return 1 + left;
if (!root->left && root->right) //右子树空则只计算左子树
return 1 + right;
return 1 + min(left, right); //左右子树均不为空则返回较小值
}
};
思考二:递归法,前序遍历形式。设置全局变量result,每次循环若当前节点为空节点不处理,若当前节点为叶子节点,则将result和当前节点的深度比较,将将较小值写入result,并处理非空孩子节点。
代码:
class Solution {
public:
int result; //记录当前最小深度
void getMin(TreeNode* node, int depth) {
if (!node) return; //函数递归终止条件
if (!node->left && !node->right) //中 比较叶子节点深度
result = min(result, depth);
if (node->left) //左
getMin(node->left, depth + 1);
if (node->right) //右
getMin(node->right, depth + 1);
return;
}
int minDepth(TreeNode* root) {
if (!root) return result;
result = __INT_MAX__;
getMin(root, 1);
return result;
}
};
思考三:迭代法,昨天写过。
链接:第十五天| 二叉树的层序遍历、226.翻转二叉树、101. 对称二叉树
Leetcode 222.完全二叉树的节点个数
题目链接: 222 完全二叉树的节点个数
题干: 给你一棵完全二叉树的根节点
root
,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h
层,则该层包含 1~2^h
个节点。
思考一:按普通二叉树思考,递归法。每次循环计算左右子树节点个数,加上根节点返回
代码:
class Solution {
public:
int countNodes(TreeNode* root) {
if (!root) return 0;
int leftNum = countNodes(root->left); //左
int rightNum = countNodes(root->right); //右
int treeNum = leftNum + rightNum + 1; //中
return treeNum;
}
};
思考二:按普通二叉树思考,迭代法。层序遍历过程中每出队一个元素,节点个数加一
代码:
class Solution {
public:
int countNodes(TreeNode* root) {
queue<TreeNode*> que;
int num = 0;
if (root != nullptr) que.push(root);
while (!que.empty()) {
int size = que.size(); //记录每层节点个数
for (int i = 0; i < size; i++) {
TreeNode* cur = que.front();
que.pop();
num++;
//将左右非空孩子节点加入队列
if (cur->left) que.push(cur->left);
if (cur->right) que.push(cur->right);
}
}
return num;
}
};
思考三:按完全二叉树思考,递归法。
关键点:完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
- 对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
- 对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
如果整个树不是满二叉树,就递归其左右孩子,直到遇到满二叉树为止,用公式计算这个子树(满二叉树)的节点数量,来减少递归次数
如何去判断一个左子树或者右子树是不是满二叉树:
- 递归向左遍历的深度等于递归向右遍历的深度则为满二叉树(完全二叉树的子树若只有一个孩子节点必为左孩子节点)
代码:
class Solution {
public:
int countNodes(TreeNode* root) {
if (!root) return 0;//空树的情况
//满二叉树的情况
TreeNode* leftNode = root->left;
TreeNode* rightNode = root->right;
int leftDepth = 0, rightDepth = 0;
while (leftNode) { //左深度遍历
leftDepth++;
leftNode = leftNode->left;
}
while (rightNode) { //右深度遍历
rightDepth++;
rightNode = rightNode->right;
}
if (leftDepth == rightDepth) //直接代公式返回结果
return (2 << leftDepth) - 1;
//完美二叉树的情况
int leftTreeNum = countNodes(root->left); //左
int rightTreeNum = countNodes(root->right); //右
int result = leftTreeNum + rightTreeNum + 1; //中
return result;
}
};
自我总结:
递归三部曲,逐步理解单层递归逻辑的考虑思路