思路:
利用遍历二叉树的方法,记录树的最大深度
递归法:
先序遍历
先序遍历从根节点向叶结点访问,求得是树的深度
class Solution {
public:
// 先序遍历
int result;
void pre_order(TreeNode* root, int depth) {
if (root == nullptr) return ;
result = max(result, depth);
pre_order(root->left, depth + 1);
pre_order(root->right, depth + 1);
}
int maxDepth(TreeNode* root) {
result = 0;
pre_order(root, 1);
return result;
}
};
后序遍历
后序遍历从叶结点向根节点访问,求的是树的高度
class Solution {
public:
// 后序遍历
int post_order(TreeNode* root) {
if (root == nullptr) return 0;
int left_height = post_order(root->left);
int right_height = post_order(root->right);
return max(left_height, right_height) + 1;
}
int maxDepth(TreeNode* root) {
return post_order(root);
}
};
迭代法:
层序遍历
最大深度及层数
class Solution {
public:
// 层序遍历
int maxDepth(TreeNode* root) {
int depth = 0;
if (root == nullptr) return depth;
queue<TreeNode*> que;
que.push(root);
while (!que.empty()) {
depth++;
int size = que.size();
for (int i = 0; i < size; ++i) {
TreeNode* node = que.front();
que.pop();
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
cout << size << endl;
}
return depth;
}
};
和二叉树深度同理,这里只使用层序迭代遍历
class Solution {
public:
int maxDepth(Node* root) {
if (root == NULL) return 0;
int depth = 0;
queue<Node*> que;
que.push(root);
while (!que.empty()) {
depth++;
int que_size = que.size();
for (int i = 0; i < que_size; ++i) {
Node* node = que.front();
que.pop();
int child_size = node->children.size();
for (int i = 0; i < child_size; ++i) {
que.push(node->children[i]);
}
}
}
return depth;
}
};
111. 二叉树的最小深度
思路:
递归法
先序遍历
从根节点向叶结点访问,记录最小深度
class Solution {
public:
// 先序遍历
int result;
void pre_order(TreeNode* root, int depth) {
if (root->left == nullptr && root->right == nullptr) { // 在叶结点更新答案
result = min(result, depth);
return ;
}
if (root->left) pre_order(root->left, depth + 1);
if (root->right) pre_order(root->right, depth + 1);
}
int minDepth(TreeNode* root) {
result = INT_MAX;
if (root == nullptr) return 0;
pre_order(root, 1);
return result;
}
};
后序遍历
从叶结点向根节点回溯,记录最小高度
注意:这里求的是根节点到叶结点的最小距离,叶节点是两个子节点均为空才行
class Solution {
public:
// 后续遍历
int post_order(TreeNode* root) {
if (root == nullptr) return 0;
int left_h = post_order(root->left); // 左
int right_h = post_order(root->right); // 右
// 中
if (root->left == nullptr && root->right == nullptr) return min(left_h, right_h) + 1; // 叶结点开始向上记录高度
if (root->left == nullptr) return right_h + 1;
if (root->right == nullptr) return left_h + 1;
return min(left_h, right_h) + 1; // 其他情况也选择最小高度继续回溯
}
int minDepth(TreeNode* root) {
if (root == nullptr) return 0;
return post_order(root);
}
};
迭代法
层序遍历
class Solution {
public:
// 层序遍历
int minDepth(TreeNode* root) {
if (root == nullptr) return 0;
int depth = 0;
queue<TreeNode*> que;
que.push(root);
while (!que.empty()) {
depth++;
int size = que.size();
for (int i = 0; i < size; ++i) {
TreeNode* node = que.front();
que.pop();
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
if (node->left == nullptr && node->right == nullptr) return depth; // 到达的第一个叶子结点即可计算最小深度
}
}
return depth;
}
};
222. 完全二叉树的节点个数
思路:
递归法
后续遍历
统计出左右子树的结点数,加起来就是根节点的结点数
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( l o g n ) O(logn) O(logn)
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
迭代法
层序遍历
将每层的结点数加起来
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
int cnt = 0;
queue<TreeNode*> que;
que.push(root);
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; ++i) {
TreeNode* node = que.front();
que.pop();
cnt++;
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return cnt;
}
};
超级优化
由于完全二叉树的定义:
最后一层的结点可以不满,但是必须全部在最左边
递归下去,一定能找到为满完全二叉树的子树,这些子树可以直接根据树的深度计算其结点个数
判断子树为满完全二叉树的判据是:根节点到左子树最左叶结点的深度和根节点到最右叶结点的深度相同
时间复杂度: O ( l o g n ∗ l o g n ) O(logn * logn) O(logn∗logn) // l o g n logn logn层,每层寻找左右子树最长分支(最坏情况长 l o g n logn logn)
空间复杂度: O ( l o g n ) O(logn) O(logn)
class Solution {
public:
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
int left_depth = 0;
int right_depth = 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
while (left) { // 统计左子树最左分支的深度
left = left->left;
left_depth++;
}
while (right) { // 统计右子树最右分支的深度
right = right->right;
right_depth++;
}
if (left_depth == right_depth) { // 当前root及其子树为满完全二叉树,直接计算其结点个数即可 2^h - 1
return (2 << left_depth) - 1;
}
return countNodes(root->left) + countNodes(root->right) + 1;
}
};