二叉树OJ题总结
1、平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:
一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1
示例:
![image-20230114215739662](https://i-blog.csdnimg.cn/blog_migrate/9428cbca110cd7cbbe53a9047dad9a96.png)
![image-20230114215758491](https://i-blog.csdnimg.cn/blog_migrate/4e9e6339fd95f04eae31588930ea7a83.png)
我选择了自底向上递归的做法,类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 −1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。
int height(struct TreeNode* root)
{
if (root == NULL)
{
return 0;
}
int leftHeight = height(root->left);
int rightHeight = height(root->right);
if (leftHeight == -1 || rightHeight == -1 || fabs(leftHeight - rightHeight) > 1) //此语句用来判断当前结点为根子树是否平衡
{
return -1;//不平衡就返回-1
}
else
{
return fmax(leftHeight, rightHeight) + 1;
}
}
bool isBalanced(struct TreeNode* root)
{
return height(root) >= 0;
}
2、前序遍历
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
示例:
![image-20230114221325320](https://i-blog.csdnimg.cn/blog_migrate/18f766f21c4b4b85c88559381d7041dd.png)
之前就介绍过前序遍历,是按照根->左->右的顺序来遍历
我这道题选择了迭代的方式来做
首先明确迭代的含义,就是重复反馈来逼近结果
这道的思路就是利用迭代遍历模拟了栈的存储
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
int* res = malloc(sizeof(int) * 2000);
*returnSize = 0;
if (root == NULL)
{
return res;
}
struct TreeNode* stk[2000];
struct TreeNode* node = root;
int stk_top = 0;
while (stk_top > 0 || node != NULL)
{
while (node != NULL)
{
res[(*returnSize)++] = node->val;
stk[stk_top++] = node;
node = node->left;
}
node = stk[--stk_top];
node = node->right;
}
return res;
}
3、翻转二叉树
给你一棵二叉树的根节点 root
,翻转这棵二叉树,并返回其根节点。
示例:
![image-20230114223252782](https://i-blog.csdnimg.cn/blog_migrate/5be64a124fff222b3ca5d6e8b55f0569.png)
![image-20230114223307563](https://i-blog.csdnimg.cn/blog_migrate/c6b46f49bbb7f39021057e583d3945d0.png)
看起来有点麻烦,实际上我们可以从小规模的树开始思考如何翻转
我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root
的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root
为根节点的整棵子树的翻转。
struct TreeNode* invertTree(struct TreeNode* root)
{
if(root == NULL)
{
return NULL;
}
struct TreeNode* left = invertTree(root->left);
struct TreeNode* right = invertTree(root->right);
root->left = right;
root->right = left;
return root;
}
4、对称二叉树
给你一个二叉树的根节点 root
, 检查它是否轴对称。
示例:
![image-20230114223707024](https://i-blog.csdnimg.cn/blog_migrate/7cfbdadb9db9fdd6c499ed3280af64ee.png)
![image-20230114223720584](https://i-blog.csdnimg.cn/blog_migrate/9b0a89e0f056bf2cfcf93aed2e32df57.png)
判断一个树是否对称,首先要判断左右孩子是否对称相等,还需要判断左孩子的左子树是否和右孩子的右子树对称,左孩子的右子树是否和右孩子的左子树对称
bool compare(struct TreeNode *left,struct TreeNode *right)
{
if(left == NULL && right == NULL)
return true;
if(left == NULL || right == NULL)//上边的语句已经排除了同时为NULL的可能性
return false;
if(left->val != right->val)
return false;
return compare(left->left,right->right) && compare(left->right,right->left);
}
bool isSymmetric(struct TreeNode* root)
{
if(root == NULL)
return true;
return compare(root->left,root->right);
}
5、子树问题
给你两棵二叉树 root
和 subRoot
。检验 root 中是否包含和 subRoot
具有相同结构和节点值的子树。如果存在,返回 true
;否则,返回 false
。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
示例:
![image-20230114224147629](https://i-blog.csdnimg.cn/blog_migrate/d028a8ad85a0e12175775a67a8536de2.png)
![image-20230114224205572](https://i-blog.csdnimg.cn/blog_migrate/f2e8e268033f200446df19d73d81253b.png)
判断t是否为s的子树,需要判断t是否和s的某一个子树相同,所以此题就是判断两棵树是否相同的逻辑。
bool compare(struct TreeNode* root, struct TreeNode* subRoot)
{
if(root==NULL && subRoot==NULL)
{
return true;
}
if(root==NULL||subRoot==NULL)
{
return false;
}
if(root->val!=subRoot->val)
{
return false;
}
return compare(root->left,subRoot->left)&& compare(root->right,subRoot->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
if(root==NULL)
{
return false;
}
return compare(root,subRoot)||isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}
6、二叉树遍历
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
示例:
这道题的解题思路就是,在先序遍历的过程中构建每一个节点
#include<stdio.h>
#include<stdlib.h>
typedef struct BTNode
{
char val;
struct BTNode* left;
struct BTNode* right;
}BTNode;
struct BTNode* BinaryTreeCreate(char* p,int* k)
{
if(p[*k] == '#')
{
(*k)++;
return NULL;
}
BTNode* tmp=(BTNode*)malloc(sizeof(BTNode));
if(tmp == NULL)
{
exit(-1);
}
tmp->val=p[*k];
(*k)++;
tmp->left=BinaryTreeCreate(p,k);
tmp->right=BinaryTreeCreate(p,k);
return tmp;
}
void Inorder(struct BTNode* root)
{
if(root == NULL)
return;
Inorder(root->left);
printf("%c ",root->val);
Inorder(root->right);
}
int main()
{
char c[101];
while(scanf("%s",c) != EOF)
{
int k=0;
BTNode* root=BinaryTreeCreate(c,&k);
Inorder(root);
}
return 0;
}