题目:104. 二叉树的最大深度
链接: leetcode题目链接
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
实现算法:递归后序遍历
前序求深度,后序求高度
代码的逻辑其实是求的根节点的高度,根节点的高度就是二叉树的最大深度,所以一般通过后序求的根节点高度来求的二叉树最大深度。
class solution {
public:
int getdepth(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;
}
int maxDepth(TreeNode* root) {
return getdepth(root);
}
};
//精简版
class solution {
public:
int maxDepth(TreeNode* root) {
if (root == null) return 0;
return 1 + max(maxDepth(root->left), maxDepth(root->right));
}
};
//前序遍历(回溯)
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) { // 左
depth++; // 深度+1
getdepth(node->left, depth);
depth--; // 回溯,深度-1
}
if (node->right) { // 右
depth++; // 深度+1
getdepth(node->right, depth);
depth--; // 回溯,深度-1
}
return ;
}
int maxDepth(TreeNode* root) {
result = 0;
if (root == NULL) return result;
getdepth(root, 1);
return result;
}
};
p.s.
递归一直没搞懂,看了好几天,一开始是层序遍历暴力过的,总算有了点头绪,但有时候确定不好参数和返回值。
题目:111. 二叉树的最小深度
链接: leetcode题目链接
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
实现算法:递归后序遍历
求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。,注意是叶子节点。
如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。
反之,右子树为空,左子树不为空,最小深度是 1 + 左子树的深度。
最后如果左右子树都不为空,返回左右子树深度最小值 + 1 。
class Solution {
public:
int getDepth(TreeNode* node) {
if (node == NULL) return 0;
int leftDepth = getDepth(node->left); // 左
int rightDepth = getDepth(node->right); // 右
// 中
// 当一个左子树为空,右不为空,这时并不是最低点
if (node->left == NULL && node->right != NULL) {
return 1 + rightDepth;
}
// 当一个右子树为空,左不为空,这时并不是最低点
if (node->left != NULL && 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 == 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));
}
};
p.s.
1.最小高度要求必须探索到叶子节点,而不能是单侧树。
2.不能直接对比左右节点的最小高度,否则会犯上述错误,一侧节点为空,另一侧节点有树,不能算最小高度。
//前序遍历
class Solution {
private:
int result;
void getdepth(TreeNode* node, int depth) {
// 函数递归终止条件
if (root == nullptr) {
return;
}
// 中,处理逻辑:判断是不是叶子结点
if (root -> left == nullptr && root->right == nullptr) {
res = min(res, depth);
}
if (node->left) { // 左
getdepth(node->left, depth + 1);
}
if (node->right) { // 右
getdepth(node->right, depth + 1);
}
return ;
}
public:
int minDepth(TreeNode* root) {
if (root == nullptr) {
return 0;
}
result = INT_MAX;
getdepth(root, 1);
return result;
}
};
题目:110. 平衡二叉树
链接: leetcode题目链接
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
提示:
1).树中的节点数在范围 [0, 5000] 内
2).-10^4 <= Node.val <= 10^4
实现算法:后序遍历
class Solution {
public:
// 返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树了则返回-1
int getHeight(TreeNode* node) {
if (node == NULL) {
return 0;
}
int leftHeight = getHeight(node->left);
if (leftHeight == -1) return -1;
int rightHeight = getHeight(node->right);
if (rightHeight == -1) return -1;
return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);
}
bool isBalanced(TreeNode* root) {
return getHeight(root) == -1 ? false : true;
}
};
p.s.
如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。
记得判断的时候加上返回已判断出不符合条件的情况!!!
题目:404. 左叶子之和
链接: leetcode题目链接
给定二叉树的根节点 root ,返回所有左叶子之和。
提示:
1).节点数在 [1, 1000] 范围内
2).-1000 <= Node.val <= 1000
实现算法:后序遍历
判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子
左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点。
单层递归的逻辑:当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == NULL) return 0;
if (root->left == NULL && root->right== NULL) return 0;
int leftValue = sumOfLeftLeaves(root->left); // 左
if (root->left && !root->left->left && !root->left->right) { // 左子树就是一个左叶子的情况
leftValue = root->left->val;
}
int rightValue = sumOfLeftLeaves(root->right); // 右
int sum = leftValue + rightValue; // 中
return sum;
}
};
p.s.
一开始不太理解左叶子节点的记录意思,我觉得现在可以理解为,若左节点不是叶子节点,就继续找左子树中的左叶子节点,若左节点是叶子节点,那也不存在后序左子树了。
自我实现
层序遍历
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
queue<TreeNode*> tree;
if(root==NULL) return 0;
tree.push(root);
int sum=0;
while(!tree.empty()){
int size=tree.size();
while(size--){
TreeNode* cur=tree.front();
tree.pop();
if(cur->right!=NULL) tree.push(cur->right);
if(cur->left!=NULL){
tree.push(cur->left);
cur=cur->left;
if(cur->left==NULL&cur->right==NULL) sum+=cur->val;
}
}
}
return sum;
}
};
p.s.
层序遍历贼简单
做题心得
啊!!!递归好难,总是判断不清,慢慢来吧,有点跟不上了