感谢各位大佬的光临,希望和大家一起进步,望得到你的三连,互三支持,一起进步
文章目录
- 一.对称二叉树
- 二.翻转二叉树
- 三.判断子树
- 四.还原二叉树
- 总结
一.对称二叉树. - 力扣(LeetCode)
给你一个二叉树的根节点
root
, 检查它是否轴对称。示例 1:
输入:root = [1,2,2,3,4,4,3] 输出:true
解题思路:
判断一个树是否对称,首先要判断左右孩子是否对称相等,还需要判断左孩子的左子树是否和右孩子的右子树对称,左孩子的右子树是否和右孩子的左子树对称。
其实就是根和根比,左子数和右子数比右子数和左子数去比,开始进行空的判断,然后利用地归左右根比较,根与根要一样,左等于右右等于左,就可以了。
bool _isSymmetric(struct TreeNode* left, struct TreeNode* right)
{
if (left == NULL && right == NULL)
return true;
if (left == NULL || right == NULL)
return false;
return left->val == right->val
&& _isSymmetric(left->left, right->right)
&& _isSymmetric(left->right, right->left);
}
bool isSymmetric(struct TreeNode* root) {
if (root == NULL)
return true;
return _isSymmetric(root->left, root->right);
}
二.翻转二叉树
226. 翻转二叉树 - 力扣(LeetCode)
给你一棵二叉树的根节点
root
,翻转这棵二叉树,并返回其根节点。示例 1:
输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]
解题思路:
翻转每一棵树的左右子树根节点
二叉树的翻转,我才开始想的是用层序遍历来解,应该是可解的,但是有点复杂,我也没想了,设一个值保存树的左子树,右子树去覆盖左子树,在把右赋值给,这样就完成了一次翻转,然后在递归遍历左右就可以了,其实很简单,但是当时没有想到,注意细节,这里是翻转的结点不是值,所以原来的只会跟着过来,所以为什么后面递归遍历可以走的通
void _invertTree(struct TreeNode* root)
{
if (root)
{
struct TreeNode* tmp = root->left;
root->left = root->right;
root->right = tmp;
_invertTree(root->left);
_invertTree(root->right);
}
}
struct TreeNode* invertTree(struct TreeNode* root) {
_invertTree(root);
return root;
}
三.判断子树
给你两棵二叉树
root
和subRoot
。检验root
中是否包含和subRoot
具有相同结构和节点值的子树。如果存在,返回true
;否则,返回false
。二叉树
tree
的一棵子树包括tree
的某个节点和这个节点的所有后代节点。tree
也可以看做它自身的一棵子树。示例 1:
输入:root = [3,4,5,1,2], subRoot = [4,1,2] 输出:true
解题思路:
判断t是否为s的子树,需要判断t是否和s的某一个子树相同,所以此题就是判断两棵树是否相同的逻辑。
判断子树问题我们先要知道如何判断两个树相等,知道如何判断两棵树相等子树问题就好判断了,那么如何判断呢?思路:两个节点都为空就相等,其中一个为空另一个不为空就不相等,如果没有空,就看树里面的值,如果值不一样的话就不相等,一样的话就继续递归左右,那我判断子树的话,就只需要根据节点来判断就可以了,把这棵树遍历一遍,每一个节点和子树来比前题是节点树里的值必须和子树相等
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
if (p == NULL && q == NULL)
return true;
if (p == NULL || q == NULL)
return false;
if (p->val != q->val)
return false;
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
if (root == NULL)
return false;
if (root->val == subRoot->val && isSameTree(root, subRoot))
return true;
return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
四.还原二叉树
给定一棵二叉树的前序遍历序列和中序遍历序列,要求计算该二叉树的高度。
输入格式:
输入首先给出正整数 n(≤50),为树中结点总数。随后 2 行先后给出前序和中序遍历序列,均是长度为 n 的不包含重复英文字母(区别大小写)的字符串。
输出格式:
输出为一个整数,即该二叉树的高度。
输入样例:
9 ABDFGHIEC FDHGIBEAC
输出样例:
5
还原二叉树,就是已知一个前序或后序和一个中序来把一棵二叉树还原,那为什么是前序或后序加一个中序而不是前序和后序了,因为前和后只能确定根节点,无法知道根节点的位置,只有中序可以知道根节点的位置
思路:首先判断是否为空,如果是长度为0肯定返回空,如果长度不为零的话,先开辟一个节点,把根结点存进去,然后再中序中找到根结点的位置,然后再递归左右区间
注意:为什么左是Pre + 1, In, i,右是Pre + i + 1, In + i + 1, len - i - 1
Pre + 1是找下一个根,因为是前序遍历,根左子树右子树,In, i是因为在前一个中序中已经找到了位置,所以下一个左子树的根肯定在0到i中,Pre + i + 1是找右边的根,In + i + 1是确实右边的根在中序中的位置,len - i - 1还剩多少长度。
#define _CRT_SECURE_NO_WARNINGS 1;
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define MAX 51
typedef struct BinTree
{
char Data;
struct BinTree*left; //左子树
struct BinTree*right; //右子树
}TreeNode;
TreeNode* Recover(char Pre[MAX], char In[MAX], int len) //建立二叉树
{
TreeNode* tmp;
int i=0;
if (len==0)
{
return NULL;
}
else
{
//存放根结点
tmp = (TreeNode*)malloc(sizeof(TreeNode));
assert(tmp);
tmp->Data = Pre[0];
//确定根结点在中序中的位置
for (i = 0; i < len; i++)
{
if (Pre[0] == In[i])
break;
}
tmp->left = Recover(Pre + 1, In, i);
tmp->right = Recover(Pre + i + 1, In + i + 1, len - i - 1);
}
return tmp;
}
int maxDepth(TreeNode* tree)
{
if (tree == NULL)
return 0;
int leftDepth = maxDepth(tree->left);
int rightDepth = maxDepth(tree->right);
return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}
int main()
{
TreeNode* Tree;
char xianxu[MAX] = { 0 };
char zhongxu[MAX] = { 0 };
int N = 0;
int H = 0;
scanf("%d", &N);
scanf("%s%s", xianxu, zhongxu);
Tree = Recover(xianxu, zhongxu, N);
H = maxDepth(Tree);
printf("%d\n", H);
return 0;
}
总结
补充了一些关于二叉树的习题,和自己的一些做题经验。