对于二叉树,今天给大家带来了九道开胃小菜:
目录
1. 单值二叉树
2. 相同的树
3. 二叉树的最大深度
4. 另一课树的子树
5. 二叉树的前序构建
6. 二叉树的前序遍历
7. 对称二叉树
8. 翻转二叉树
9. 平衡二叉树
题目地址:965. 单值二叉树 - 力扣(Leetcode)
解题思路:遍历二叉树时将每一个节点的值与二叉树根节点的值进行比较,相同返回true与其节点左子树和右子树比较之后的且值,如果不相同就直接返回false。
解题代码:
bool CheckTreeVal(int n,struct TreeNode* root)
{
if(root==NULL)
return true;
bool L=CheckTreeVal(n,root->left);
bool R=CheckTreeVal(n,root->right);
if(root->val==n)
return true&&L&&R;
else
return false;
}
bool isUnivalTree(struct TreeNode* root){
return CheckTreeVal(root->val,root);
}
题目地址:100. 相同的树 - 力扣(Leetcode)
解题思路:同时遍历两棵树相同的节点,如果都为空返回true,如果一个节点为空一个节点不为空(很显然两棵树不相同),返回false。如果两个节点都不为空,我们比较两个节点的值,不相同直接返回false,相同我们递归比较其左子树和右子树,最后将返回结果与一下得到最终结果。
解题代码:
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);
}
题目地址:104. 二叉树的最大深度 - 力扣(Leetcode)
解题思路:遍历二叉树时,记录每一层节点左子树和右子树的深度返回大的子树值+1,层层统计,最后计算出二叉树的最大深度。
解题代码:
int maxDepth(struct TreeNode* root){
if(root==NULL)
return 0;
int L=maxDepth(root->left);
int R=maxDepth(root->right);
return L>R?L+1:R+1;
}
题目地址:572. 另一棵树的子树 - 力扣(Leetcode)
该题是相同的树的升级版
解题思路:遍历root树的每一个节点,如果发现有节点值和subRoot根节点值相同就将此节点及以下的子树和subRoot树相比较,判断是否为相同的两棵树,如果是就返回true,否则返回false。最后将所有的判断结果或一下,就能解决掉这一题了。
解题代码:
bool Check(struct TreeNode* root,struct TreeNode* subRoot)//判断是否为相同的两棵树
{
if(subRoot==NULL&&root==NULL)
return true;
if(root==NULL||subRoot==NULL)
return false;
if(root->val!=subRoot->val)
return false;
return Check(root->left,subRoot->left)&&Check(root->right,subRoot->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
if(root==NULL)
return false;
bool R=false;//保存判断结果
if(root->val==subRoot->val)//如果节点与subRoot根节点值相同就判断是否为相同的两棵树
{
R=Check(root,subRoot);
}
return R||isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);//遍历root的每一个节点,并将所有判断结果相或
}
题目地址:二叉树遍历_牛客题霸_牛客网 (nowcoder.com)
解题思路:前序构建二叉树时,我们按前序遍历二叉树思路进行即可。首先将当前节点创建完毕,再递归构建其左孩子节点,最后递归构建其右孩子节点。在递归构建时,我们需要对字符串进行操作,每构建一个节点需要遍历字符串下一个字符,这时我们可以传指针来解决这个问题,每构建一个节点后将指针所指向的数据加1。
解题代码:
#include
#include
typedef struct BinaryTreeNode {
//数据
char data;
struct BinaryTreeNode* Left;//指向左孩子
struct BinaryTreeNode* Right;//指向右孩子
} BTNode;
void InOrder(BTNode* root)//中序遍历
{
if (root == NULL)//如果是空树就直接结束
return;
InOrder(root->Left);
printf("%c ", root->data);
InOrder(root->Right);
}
BTNode* PrevOrderCreate(char*s,int* n)
{
if(*(s+*n)=='#')
{
(*n)++;
return NULL;
}
BTNode*root=(BTNode*)malloc(sizeof(BTNode));//构建当前节点
root->data=s[(*n)++];
root->Left=PrevOrderCreate(s, n);//构建节点左孩子
root->Right=PrevOrderCreate(s, n);//构建节点右孩子
return root;
}
int main() {
char str[100];
int n=0;
scanf("%s", str);
BTNode* Tree=PrevOrderCreate(str,&n);
InOrder(Tree);
return 0;
}
题目地址:144. 二叉树的前序遍历 - 力扣(Leetcode)
解题思路:该题相比于单纯的二叉树前序遍历多了要返回一个前序遍历后的数组。对此我们先要计算出二叉树所有的节点的个数,然后创建一个 二叉树所有的节点的个数的数组,在前序遍历时将遍历节点值依次插入到数组中即可。
对于这题的迭代解法会在后期的C++中向大家进行讲解(C语言要造大轮子,不方便)。
解题代码:
int CountTreeSize(struct TreeNode*root)
{
return root==NULL?0:1+CountTreeSize(root->left)+CountTreeSize(root->right);
}
void PrevOrder(struct TreeNode* root, int* arr,int*n)
{
if(root==NULL)
return;
arr[(*n)++]=root->val;
PrevOrder(root->left,arr,n);
PrevOrder(root->right,arr,n);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize=CountTreeSize(root);
int *arr=(int*)malloc(sizeof(int)*(*returnSize));
int n=0;
PrevOrder(root,arr,&n);
return arr;
}
题目地址:101. 对称二叉树 - 力扣(Leetcode)
解题思路:该题我们可以发现对称二叉树的左子树左节点和右子树的右节点、左子树右节点和右子树的左节点是相同的,这样的话我们可以递归将左子树所有的右节点与右子树的左节点、左子树左节点和右子树的右节点相比较,不相同返回false,直到对比到空节点(说明相比较过的节点都相同)返回true,最后与一下比较结果,此题轻松解决~
解题代码:
bool _isSymmetric(struct TreeNode*left,struct TreeNode*right)
{
if(left==NULL&&right==NULL)
return true;
if(left==NULL||right==NULL)
return false;
if(left->val!=right->val)
return false;
return _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的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以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;
}
题目地址:110. 平衡二叉树 - 力扣(Leetcode)
解题思路:我们在遍历二叉树时,当前遍历到的节点,首先计算左右子树的高度,如果左右子树的高度差是否超过1返回false,否则继续进行遍历并计算高度,遇到空树返回true,最后将所有返回结果与一下得到最终结果即可。
解题代码:
int maxDepth(struct TreeNode* root)
{
if(root==NULL)
return 0;
int L=maxDepth(root->left);
int R=maxDepth(root->right);
return L>R?L+1:R+1;
}
bool isBalanced(struct TreeNode* root)
{
if(root==NULL)
return true;
int dif=maxDepth(root->left)-maxDepth(root->right);
if(dif<-1||dif>1)
return false;
return isBalanced(root->left)&&isBalanced(root->right);
}
今天的二叉树特训到这就结束啦,各位有没有吃饱呢。
后续会向大家带来排序经典例题,敬请期待~