day14 二叉树part2 226.翻转二叉树 101.对称二叉树 104.二叉树的最大深度 111.二叉树的最小深度
226.翻转二叉树
题目链接:[226.翻转二叉树](226. 翻转二叉树 - 力扣(LeetCode))
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
思路:将每个结点的左右孩子交换一下,返回根节点。注意如果使用中序遍历,在访问到根节点后交换了左右孩子,然后依然还要访问左孩子,才能交换整颗树。
写二叉树的题目先搞清楚用什么遍历顺序。
// 先序遍历
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) return root;
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
// 中序
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == nullptr) return root;
invertTree(root->left);
swap(root->left, root->right);
invertTree(root->left);
return root;
}
};
101.对称二叉树
题目链接:[101.对称二叉树](101. 对称二叉树 - 力扣(LeetCode))
题干:给你一个二叉树的根节点 root
, 检查它是否轴对称。
思路:
- 首先是递归函数的参数,判断左右是否轴对称,需要对比的是左右两个子树是否对称,应该在左右子树都进行遍历,传入左右两个结点指针。
- 终止条件,左右都为空,返回true;左右一个为空返回false;左右值不等返回false,其余的情况就是还需要继续递归判断左子树的孩子和右子树的孩子的对称情况
- 单层遍历,采用后序遍历,需要判断内侧和外侧的对称情况才能确定该层是否对称。
class Solution {
public:
bool traverse(TreeNode* left, TreeNode* right) {
if (left == nullptr && right == nullptr) return true;
else if (left == nullptr || right == nullptr) return false;
else if (left->val != right->val) return false;
else {
// 此时才需要递归判断下一层
bool isOuter = traverse(left->left, right->right);
bool isInner = traverse(left->right, right->left);
return isInner && isOuter;
}
}
bool isSymmetric(TreeNode* root) {
if (root == nullptr) return true;
return traverse(root->left, root->right);
}
};
104.二叉树的最大深度
题目链接:[104.二叉树的最大深度](104. 二叉树的最大深度 - 力扣(LeetCode))
题干:给定一个二叉树 root
,返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
思路:高度是从叶节点到根节点,深度是从根节点到叶结点。通常求高度采用后序遍历,从叶节点开始返回,然后每层加1;求深度采用前序遍历,每遍历一层深度加1。而最大深度等于最大高度,本题采用前序或者后序都可以。
采用后序,遍历到叶子结点返回0,然后每一层根结点返回左右子树最大深度加1.
class Solution {
public:
int maxDepth(TreeNode* root) {
// 递归
if (root == nullptr) return 0;
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return max(left, right) + 1;
}
};
采用前序,需要使用一个变量来纪录遍历时的最大深度。
class Solution {
public:
int result = 0;
void getDepth(TreeNode* root, int depth) {
if (root == nullptr) return;
result = max(depth, result);
getDepth(root->left, depth + 1); //蕴含了回溯
// 相当于
// depth++;
// getDepth(root->left, depth);
// depth--;
getDepth(root->right, depth + 1);
}
int maxDepth(TreeNode* root) {
getDepth(root, 1);
return result;
}
};
111.二叉树的最小深度
题目链接:[111.二叉树的最小深度](111. 二叉树的最小深度 - 力扣(LeetCode))
题目:给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
**说明:**叶子节点是指没有子节点的节点。
思路:最小深度是根节点到最近叶子结点的节点数量,也就是说当根结点一个孩子为空时,应该返回另一个孩子的最小深度,这是与求最大深度的不同。
错误代码,当根节点左孩子为空时,会把左孩子作为最小深度,求得最小深度为1。
class Solution {
public:
int minDepth(TreeNode* root) {
// 递归
if (root == nullptr) return 0;
int left = minDepth(root->left);
int right = minDepth(root->right);
return min(left, right) + 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 == nullptr) return 0;
// if (root->left == nullptr && root->right == nullptr) return 1;
// 左右中
if (root->left == nullptr && root->right != nullptr) {
return minDepth(root->right) + 1;
} else if (root->left != nullptr && root->right == nullptr) {
return minDepth(root->left) + 1;
} else {
int left = minDepth(root->left); // 左
int right = minDepth(root->right); // 右
return min(left, right) + 1; // 中
}
}
};