一、题目打卡
1.1 二叉树的最大深度
leetcode链接:. - 力扣(LeetCode)
class Solution {
public:
int maxDepth(TreeNode* root) {
if(!root) return 0;
return max(maxDepth(root->left),maxDepth(root->right))+1;
}
};
递归的方法比较直观,将这个问题看作是子问题,每一个子问题是返回两个子树中最大的深度,注意一下终止条件和返回上一层的加 1 操作。
class Solution {
public:
int maxDepth(TreeNode* root) {
if(!root) return 0;
int res = 0;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int size = q.size();
while(size--){
TreeNode* tmp = q.front();
q.pop();
if(tmp->left) q.push(tmp->left);
if(tmp->right) q.push(tmp->right);
}
res++;
}
return res;
}
};
迭代的方法其实也比较直观,模拟的入队列和队列的过程,其实就是统计层序遍历最后返回值中容器大小。
接着阅读了这个内容:代码随想录,其实有更多的认识,自己写的其实是通过统计根节点的高度达到目的的,本身这个也可以通过前序遍历统计深度来达到目的,这样的话我感觉更像是层序的思想,代码如下:
class Solution {
private:
int max_res = 0;
void recur(TreeNode* root,int level){
if(!root) return;
max_res = max(max_res,level);
if(root->left) recur(root->left,level+1);
if(root->right) recur(root->right,level+1);
}
public:
int maxDepth(TreeNode* root) {
if(!root) return 0;
recur(root,1);
return max_res;
}
};
1.2 二叉树的最小深度
leetcode链接:. - 力扣(LeetCode)
class Solution {
public:
int minDepth(TreeNode* root) {
if(!root) return 0;
// if(!root->left && !root->right) return 1;
if(!root->left || !root->right) return root->left == nullptr ? minDepth(root->right)+1 : minDepth(root->left)+1;
return min(minDepth(root->left),minDepth(root->right)) + 1;
}
};
上面这个是今天写的,下面这个是前一天写的:
class Solution {
public:
int minDepth(TreeNode* root) {
if(!root) return 0;
int m = minDepth(root->left);
int n = minDepth(root->right);
if(m == 0 || n == 0) return m + n + 1;
else return min(m,n) + 1;
}
};
感觉这个版本更巧妙一点,而且看着也比较巧妙,前面那个本质上是一样的。
使用迭代写的话,我多维护了两个变量:
class Solution {
public:
int minDepth(TreeNode* root) {
if(!root) return 0;
queue<TreeNode*> q;
q.push(root);
int res = INT32_MAX;
int level = 1;
while(!q.empty()){
int size = q.size();
while(size--){
TreeNode* tmp = q.front();
q.pop();
if(tmp->left) q.push(tmp->left);
if(tmp->right) q.push(tmp->right);
if(!tmp->left && !tmp->right) res = min(res,level);
}
level++;
}
return res;
}
};
看了答案,突然意识到,这个是层序遍历,其实如果遇到了满足条件的叶节点,其实直接返回就行了:
class Solution {
public:
int minDepth(TreeNode* root) {
if (root == NULL) 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;
}
};
1.3 完全二叉树的节点个数
leetcode链接:. - 力扣(LeetCode)
class Solution {
public:
int countNodes(TreeNode* root) {
if(!root) return 0;
return countNodes(root->left) + countNodes(root->right) + 1;
}
};
虽然直接写出上面的代码,但是我觉得这样并不是很清晰,感觉答案的写法更清楚一点,特别是把左右中返回的思路体现的很清楚:
class Solution {
private:
int getNodesNum(TreeNode* cur) {
if (cur == NULL) 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);
}
};
迭代法其实就是统计入队列和出队列的数量,本质上是一样的,这里就不贴代码了。