目录
- 二叉树的最大深度
- 思路
- 解题方法
- 递归
- 迭代
- 复杂度
- Code
- 递归
- 迭代
- 二叉树的最小深度
- 思路
- 解题方法
- 递归
- 迭代
- 复杂度
- Code
- 递归
- 迭代
- 第一题
- 思路
- 解题方法
- 递归
- 迭代
- 复杂度
- 递归
- 迭代
- Code
- 递归
- 迭代
- 总结
二叉树的最大深度
链接: 二叉树的最大深度
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
思路
先用递归,二叉树的题目最好用的就是递归
还有一个迭代法。
解题方法
递归
递归三步:
- 确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回这棵树的深度,所以返回值为int类型。
- 确定终止条件:如果为空节点的话,就返回0,表示高度为0。
- 确定单层递归的逻辑:先求它的左子树的深度,再求右子树的深度,最后取左右深度最大的数值 再+1 (加1是因为算上当前中间节点)就是目前节点为根节点的树的深度。
迭代
使用迭代法的话,使用层序遍历是最为合适,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
复杂度
两个方法的时空复杂度一样大小
- 时间复杂度:O(n)
- 空间复杂度:O(n)
Code
递归
class solution {
public:int getdepth(TreeNode* node) {if (node == nullptr) 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);}
};
迭代
class solution {
public:int maxDepth(TreeNode* root) {if (root == nullptr) return 0;int depth = 0;queue<TreeNode*> que;que.push(root);while(!que.empty()) {int size = que.size();depth++; // 记录深度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);}}return depth;}
};
二叉树的最小深度
链接: 二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
思路
直觉上好像和求最大深度差不多,其实还是差不少的。
本题依然是前序遍历和后序遍历都可以,前序求的是深度,后序求的是高度。
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数后者节点数(取决于高度从0开始还是从1开始)
那么使用后序遍历,其实求的是根节点到叶子节点的最小距离,就是求高度的过程,不过这个最小距离 也同样是最小深度。
我们采用后序遍历,
注:
左右孩子都为空的节点才是叶子节点:
解题方法
递归
-
确定递归函数的参数和返回值
参数为要传入的二叉树根节点,返回的是int类型的深度。 -
确定终止条件
终止条件也是遇到空节点返回0,表示当前节点的高度为0。 -
确定单层递归的逻辑
迭代
需要注意的是,只有当左右孩子都为空的时候,才说明遍历到最低点了。如果其中一个孩子不为空则不是最低点
复杂度
- 时间复杂度:O(n)
- 空间复杂度:O(n)
Code
递归
class Solution {
public:int getDepth(TreeNode* node) {if (node == nullptr) return 0;int leftDepth = getDepth(node->left); // 左int rightDepth = getDepth(node->right); // 右// 中// 当一个左子树为空,右不为空,这时并不是最低点if (node->left == nullptr && node->right != NULL) { return 1 + rightDepth;} // 当一个右子树为空,左不为空,这时并不是最低点if (node->left != nullptr && node->right == NULL) { return 1 + leftDepth;}int result = 1 + min(leftDepth, rightDepth);return result;}int minDepth(TreeNode* root) {return getDepth(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()) {int size = que.size();depth++; // 记录最小深度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 && !node->right) { // 当左右孩子都为空的时候,说明是最低点的一层了,退出return depth;}}}return depth;}
};
第一题
链接: 完全二叉树的节点个数
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
思路
一棵完全二叉树的两棵子树,至少有一棵是满二叉树
利用完全二叉树性质
解题方法
递归
-
确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回以该节点为根节点二叉树的节点数量,所以返回值为int类型。
-
确定终止条件:如果为空节点的话,就返回0,表示节点数为0。
-
确定单层递归的逻辑:先求它的左子树的节点数量,再求右子树的节点数量,最后取总和再加一 (加1是因为算上当前中间节点)就是目前节点为根节点的节点数量。
迭代
复杂度
递归
- 时间复杂度:O(n)
- 空间复杂度:O(logn)
迭代
- 时间复杂度:O(n)
- 空间复杂度:O(n)
Code
递归
class Solution {
private:int getNodesNum(TreeNode* cur) {if (cur == nullptr) return 0;int leftNum = getNodesNum(cur->left); // 左int rightNum = getNodesNum(cur->right); // 右int treeNum = leftNum + rightNum + 1; // 中return treeNum;}
public:int countNodes(TreeNode* root) {return getNodesNum(root);}
};
迭代
class Solution {
public:int countNodes(TreeNode* root) {queue<TreeNode*> que;if (root != nullptr) que.push(root);int result = 0;while (!que.empty()) {int size = que.size();for (int i = 0; i < size; i++) {TreeNode* node = que.front();que.pop();result++; // 记录节点数量if (node->left) que.push(node->left);if (node->right) que.push(node->right);}}return result;}
};
总结
今天的题目不难,但要注意求二叉树的最小深度不像求二叉树最大深度,有坑。
参考文档:
链接: 二叉树的最大深度
链接: 二叉树的最小深度
链接: 完全二叉树的节点个数