104.二叉树的最大深度 (优先掌握递归)
什么是深度,什么是高度,如何求深度,如何求高度,这里有关系到二叉树的遍历方式。大家 要先看视频讲解,就知道以上我说的内容了,很多录友刷过这道题,但理解的还不够。
题目链接/文章讲解/视频讲解: 代码随想录
二叉树的深度:当前节点到根节点的长度。——根节点深度为0,故而前序遍历。
二叉树的高度:当前节点到叶子节点的长度,取最长。——叶子节点高度为0,故而后序遍历。
但是,对于一棵二叉树来讲,根节点的最大高度就是这个二叉树的最大深度,所以可以通过后序遍历来求最大深度——
int maxDepth(TreeNode* node) {
if (node == NULL) return 0;
int leftdepth = getdepth(node->left); // 左
int rightdepth = getdepth(node->right); // 右
int depth = 1 + max(leftdepth, rightdepth); // 中
return depth;
}
文章里面也介绍了前序遍历来求最大深度。递归函数首先确定每次的参数必须有的depth,否则没办法确定当前节点的子结点的深度,因为最大深度只能有一个数值,每次递归函数需要试图更新result,所以需要将result设置为类的变量,这样每次递归函数更新的都是同一个result。处理完根节点,判断是否存在左子树和右子树,不存在就直接返回,否则要继续调用递归函数来试图更新result——
class solution {
public:
int result;
void getdepth(TreeNode* node, int depth) {
result = depth > result ? depth : result; // 中
if (node->left == NULL && node->right == NULL) return ;
if (node->left) { // 左
getdepth(node->left, depth + 1);
}
if (node->right) { // 右
getdepth(node->right, depth + 1);
}
return ;
}
int maxDepth(TreeNode* root) {
result = 0;
if (root == 0) return result;
getdepth(root, 1);
return result;
}
};
最后,使用迭代法求最大深度其实就是用层序遍历法来求。
111.二叉树的最小深度 (优先掌握递归)
先看视频讲解,和最大深度 看似差不多,其实 差距还挺大,有坑。
题目链接/文章讲解/视频讲解:代码随想录
使用后序遍历。不像求最大深度那样简单,因为要排除非叶子节点的子结点为NULL的干扰,如果不处理,就会导致一旦子结点出现NULL,就会直接认定该节点的最小深度是1,但这样是不符合深度的定义的,应该是到叶子节点的长度,而叶子节点的两个子节点都要是NULL才行,这样只保证了其中一个子节点是NULL,于是要判断如果只是一个子节点为NULL,那递归调用的时候,就只用返回所求不空的子节点的最小高度加一就行——
int minDepth(TreeNode* root) {
if (root == NULL) return 0;
if (root->left == NULL && root->right != NULL) {
return 1 + minDepth(root->right);
}
if (root->left != NULL && root->right == NULL) {
return 1 + minDepth(root->left);
}
return 1 + min(minDepth(root->left), minDepth(root->right));
}
使用前序遍历。大体来说和求最大深度差不多,要注意两点,第一点是要先设置result值为INT_MAX,否则可能存在更新不了result的情况;第二点是要事先判断root是否为空,否则会直接返回INT_MAX为最小深度——
class Solution {
public:
int result=INT_MAX;
// bool find=false;
void getDepth(TreeNode* node,int depth){
if(!node) return ;
if((!node->left&&!node->right)) {
result=result<depth?result:depth;
}
if(node->left) getDepth(node->left,depth+1);
if(node->right) getDepth(node->right,depth+1);
}
int minDepth(TreeNode* root) {
if(root==NULL) return 0;
getDepth(root,1);
return result;
}
};
迭代法也可以解决,就是使用层序遍历。
222.完全二叉树的节点个数(优先掌握递归)
需要了解,普通二叉树 怎么求,完全二叉树又怎么求
题目链接/文章讲解/视频讲解:代码随想录
普通二叉树——
递归方法——
int countNodes(TreeNode* root) {
if (root == NULL) return 0;
return 1 + countNodes(root->left) + countNodes(root->right);
}
迭代方法——
使用层序遍历即可。
完全二叉树——
首先由于是完全二叉树,所以必然存在子树是满二叉树,而计算满二叉树的节点数量是很容易的,直接调用公式即可(2<<深度-1),所以一旦知道是满二叉树就意味着剩下的节点不用继续遍历了。这时候可以在每次递归调用之前,先行判断是否满二叉树(判断方法:对于完全二叉树来讲,只要满足最左叶子节点的深度和最右叶子节点的深度相等,即意味着满二叉树)——
int countNodes(TreeNode* root) {
if (root == nullptr) return 0;
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
while (left) { // 求左子树深度
left = left->left;
leftDepth++;
}
while (right) { // 求右子树深度
right = right->right;
rightDepth++;
}
if (leftDepth == rightDepth) {
return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
}
return countNodes(root->left) + countNodes(root->right) + 1;
}