代码随想录算法训练营第十六天|LeetCode104.二叉树的最大深度、LeetCode111.二叉树的最小深度、LeetCode222.完全二叉树的节点个数
2023年3月16日
第三十天补
文章目录
104. 二叉树的最大深度
题目链接:104. 二叉树的最大深度
思路:
- 该题目比较简单,我这里用递归和迭代分别实现,思路会在代码里面加注释
递归实现
时间复杂度:O(n)
,空间复杂度O(n)
代码:
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root==nullptr)return 0;
else
{
// 根树的深度就是左右子树最大深度+1
return std::max(maxDepth(root->left),maxDepth(root->right))+1;
}
}
};
迭代实现
时间复杂度:O(n)
,空间复杂度O(n)
代码:
class Solution {
public:
// 层序遍历,每到一个新层,高度+1
int maxDepth(TreeNode* root) {
int depth = 0;
std::queue<TreeNode*> stk;
int cur_size = 0;
int next_size = 0;
if(root!=nullptr)
{
stk.push(root);
++cur_size;
}
while(!stk.empty())
{
auto node = stk.front();
if(node->left!=nullptr)
{
stk.push(node->left);
++next_size;
}
if(node->right!=nullptr)
{
stk.push(node->right);
++next_size;
}
--cur_size;
stk.pop();
if(cur_size==0)
{
++depth;
cur_size= next_size;
next_size = 0;
}
}
return depth;
}
};
总结:
- 难度不大,不过这种题目思路一定要清楚些
- 做题体验:
哈哈
(哈哈
>嘿嘿
>哎哎
>嘤嘤
) - 时间:
未计
一刷
111. 二叉树的最小深度
题目链接:111. 二叉树的最小深度
思路:
- 这题相对求最大深度稍有不同,不过也比较简单
- 我还是用递归和迭代分别实现,然后在代码里注释解释
时间复杂度:O(n)
,空间复杂度O(n)
递归法
代码:
class Solution
{
public:
int minDepth(TreeNode *root)
{
// 如果一个节点的左右子树都不为空,则取两子树深度的最小值+1即可
// 如果其中一个是空子树,则取另一个子树的深度+1
if(root==nullptr) return 0;
if(root->left == nullptr &&root->right ==nullptr)return 1;
else if(root->left == nullptr) return minDepth(root->right) +1;
else if(root->right == nullptr) return minDepth(root->left) +1;
else return std::min(minDepth(root->left),minDepth(root->right)) + 1;
}
};
迭代法
代码:
// 层序遍历,遇到第一个叶子节点,就返回当前的深度
class Solution
{
public:
int minDepth(TreeNode *root)
{
int depth = 0;
std::queue<TreeNode *> stk;
int cur_size = 0;
int next_size = 0;
if (root != nullptr)
{
stk.push(root);
++cur_size;
}
while (!stk.empty())
{
auto node = stk.front();
if (node->left == nullptr && node->right == nullptr)
{
return depth + 1;
}
if (node->left != nullptr)
{
stk.push(node->left);
++next_size;
}
if (node->right != nullptr)
{
stk.push(node->right);
++next_size;
}
--cur_size;
stk.pop();
if(cur_size==0)
{
cur_size = next_size;
next_size = 0;
++depth;
}
}
return depth;
}
};
总结:
- 难度不大,不过这种题目思路一定要清楚些
- 做题体验:
哈哈
(哈哈
>嘿嘿
>哎哎
>嘤嘤
) - 时间:
未计
一刷
222. 完全二叉树的节点个数
题目链接:222. 完全二叉树的节点个数
思路:
- 满二叉树是叶子节点全部在同一层的树
- 而完全二叉树指最下层节点全部都左连续,完全二叉树包含满二叉树
- 这道题我写三个解法
- 第一个解法是对数递归求节点个数,这种方式对任何的二叉树都适用
- 第二个解法是针对完全二叉树特性,实现一种遍历更少节点的求法,具体思路在解法里再讲
- 第三个解法是迭代法,同样也是对任何二叉树适用
时间复杂度:O(n)
,空间复杂度O(n)
通用递归
代码:
class Solution
{
public:
int countNodes(TreeNode *root)
{
if (root == nullptr)
return 0;
else
// 将左子树的节点个数和右子树节点个数想加再加上当前节点
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
完全二叉树递归
思路:
- 完全二叉树可以分成若干个深度不等的满二叉树
- 对满二叉树的节点个数求值就可以使用数学公式
代码:
class Solution
{
public:
int countNodes(TreeNode *root)
{
if(root == nullptr)return 0;
// 获取当前节点左右树边的长度,如果相等,那这一部分肯定是满二叉树
int leftDepth = getLeftDepth(root);
int rightDepth = getRightDepth(root);
if (leftDepth == rightDepth)
{
// 是用满二叉树求值公式
return getManTreeNodeCount(leftDepth);
}
else
{
// 递归判断左右子树是不是满二叉树
return countNodes(root->left) + countNodes(root->right) + 1;
}
}
// 左边深度
int getLeftDepth(TreeNode *node)
{
if (node == nullptr)
return 0;
else
return getLeftDepth(node->left) + 1;
}
// 右边深度
int getRightDepth(TreeNode *node)
{
if (node == nullptr)
return 0;
else
return getRightDepth(node->right) + 1;
}
int getManTreeNodeCount(int depth)
{
return chengfang(depth) - 1;
}
int chengfang(int mi)
{
int result = 1;
while (mi--)
{
result *= 2;
}
return result;
}
};
通用迭代
代码:
// 层序遍历累加求值
class Solution
{
public:
int countNodes(TreeNode *root)
{
std::queue<TreeNode *> nodeQue;
if (root != nullptr)
{
nodeQue.push(root);
++count;
}
while (!nodeQue.empty())
{
auto node = nodeQue.front();
nodeQue.pop();
if (node->left != nullptr)
{
nodeQue.push(node->left);
++count;
}
if (node->right != nullptr)
{
nodeQue.push(node->right);
++count;
}
}
return count;
}
int count = 0;
};
总结:
*
- 做题体验:
哈哈
(哈哈
>嘿嘿
>哎哎
>嘤嘤
) - 时间:
未计
一刷