单值二叉树
题目链接:LeetCode965.单值二叉树
题目:如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true
;否则返回 false
。
题目分析:
这题我们用分治的思想来解决:分治思想即将一个大的问题无限划分为一个个小的子问题,在将子问题继续分解到不能分解为止。
这个题目我们可以使用递归来判断根节点是不是和左子树所有的值相等,判断根节点是不是和右子树中所有值相等。
题解:
bool isUnivalTree(struct TreeNode* root)
{
if(root==NULL)//根为空,符合题目要求返回true
return true;
//在root指向的左子树不为空的情况下,若root指向左子树的值不等于root指向的值,则返回false
if(root->left&&root->left->val!=root->val)
return false;
//在root指向的右子树不为空的情况下,若root指向右子树的值不等于root指向的值,则返回false
if(root->right&&root->right->val!=root->val)
return false;
//继续递归左子树和右子树
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}
相同的树
题目链接:LeetCode100.相同的树
题目:给你两棵二叉树的根节点 p
和 q
,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
题目解析:
1.当两棵树的当前节点都为空时返回true.
2.其中一个为NULL,另外一个不为空时返回false.
3.两个同时不为空,且值不想等,返回false.
4.满足条件返回,不满足条件继续递归判断左右子树是否相等。
题解:
bool isSameTree(struct TreeNode* p, struct TreeNode* q)
{
//p和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);
}
对称二叉树
题目链接:LeetCode101.对称二叉树
题目:给你一个二叉树的根节点 root , 检查它是否轴对称。
题目解析:
这个题目需要我们判断此二叉树是不是对称二叉树,对称二叉树即根节点的左子树和右子树成镜像对称。这题我们可以借助上一题的思路,将一颗非空二叉树的左子树和右子树独立出来,然后判断它的左右子树是不是镜像对称二叉树。
题解:
bool _isSymmetric(struct TreeNode* p,struct TreeNode*q)
{
//p与q均为空
if(p==NULL&&q==NULL)
return true;
//其中一个节点为空
if(p==NULL||q==NULL)
return false;
//判断p的值是否与q的值相同,若相同,继续递归p,q的左右子树判断
//p的左子树与q的右子树比较,p的右子树与q的左子树比较
return p->val==q->val&&_isSymmetric(p->left,q->right)&&_isSymmetric(p->right,q->left);
}
bool isSymmetric(struct TreeNode* root)
{
//root为空,满足题目条件
if(root==NULL)
return true;
//判断左右子树是否镜像对称
return _isSymmetric(root->left,root->right);
}
二叉树的前序遍历
题目链接:LeetCode144.二叉树的前序遍历
题目:给你二叉树的根节点 root
,返回它节点值的 前序
遍历。
题解:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//计算二叉树结点的个数,若不为空树,则递归左右子树计数,最后加上根节点。最终结果就是二叉树结点个数
int TreeNodeSize(struct TreeNode* root)
{
return root==NULL?0:TreeNodeSize(root->left)+TreeNodeSize(root->right)+1;
}
//前序遍历函数
void _preorderTraversal(struct TreeNode*root,int*a,int*i)
{
//根节点为空 - 递归结束条件
if(root==NULL)
return;
//将root指向的值存入数组a中
a[(*i)++]=root->val;
_preorderTraversal(root->left,a,i);//递归遍历左子树
_preorderTraversal(root->right,a,i);//递归遍历右子树
}
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
//计算二叉树节点个数
int size=TreeNodeSize(root);
//将size赋值为*returnSize
*returnSize=size;
//为a数组开辟空间
int*a=(int*)malloc(sizeof(int)*size);
int i=0;
//这里传i变量的时候,必须传地址
_preorderTraversal(root,a,&i);
//返回最终的数组a
return a;
}
二叉树的中序遍历
题目链接:LeetCode94.二叉树的中序遍历
题目:给定一个二叉树的根节点 root
,返回 它的 中序
遍历 。
题解:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//计算二叉树结点的个数,若不为空树,则递归左右子树计数,最后加上根节点。最终结果就是二叉树结点个数
int TreeNodeSize(struct TreeNode* root)
{
return root==NULL?0:TreeNodeSize(root->left)+TreeNodeSize(root->right)+1;
}
//二叉树中序遍历 -> 左子树 根 右子树
void _inorderTraversal(struct TreeNode*root,int*a,int*i)
{
//若root为空,则返回
if(root==NULL)
return;
_inorderTraversal(root->left,a,i);//二叉树的左子树遍历
a[(*i)++]=root->val;//将根节点的值存入数组a
_inorderTraversal(root->right,a,i);//二叉树的右子树遍历
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
int size=TreeNodeSize(root);//计算二叉树的结点个数
*returnSize=size;//将结点个数赋值给*returnSize,否则程序通不过
int*a=(int*)malloc(sizeof(int)*size);//动态开辟数组a储存遍历的数
int i=0;
_inorderTraversal(root,a,&i);//这里需要传i遍历的地址
return a;//返回目标数组
}
二叉树的后序遍历
题目链接:LeetCode145.二叉树的后序遍历
题目:给你一棵二叉树的根节点 root
,返回其节点值的 后序遍历
。
题解:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//计算二叉树结点的个数,若不为空树,则递归左右子树计数,最后加上根节点。最终结果就是二叉树结点个数
int TreeNodeSize(struct TreeNode*root)
{
return root==NULL?0:TreeNodeSize(root->left)+TreeNodeSize(root->right)+1;
}
//二叉树后序遍历 - 左子树 右子树 根
void _postorderTraversal(struct TreeNode*root,int*a,int*i)
{
//root为空,返回
if(root==NULL)
return;
_postorderTraversal(root->left,a,i);//递归遍历左子树
_postorderTraversal(root->right,a,i);//递归遍历右子树
a[(*i)++]=root->val;//将root指向的值存入数组a
}
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
int size=TreeNodeSize(root);//计算二叉树结点个数
*returnSize=size;
int*a=(int*)malloc(sizeof(int)*size);
int i=0;
_postorderTraversal(root,a,&i);
return a;
}
另一棵树的子树
题目链接:LeetCode572.另一棵树的子树
题目:给你两棵二叉树 root
和 subRoot
。检验 root
中是否包含和 subRoot
具有相同结构和节点值的子树。如果存在,返回 true
;否则,返回 false
。
二叉树 tree
的一棵子树包括 tree
的某个节点和这个节点的所有后代节点。tree
也可以看做它自身的一棵子树。
题目分析:
左边树中每一棵子树都比较一下isSameTree,遍历左边树的每一个节点,做子树的根,根右边的子树都比较一下,看是不是相同的树。
题解:
bool isSameTree(struct TreeNode*root,struct TreeNode* subRoot)
{
if(root==NULL&&subRoot==NULL)
return true;
if(root==NULL||subRoot==NULL)
return false;
return root->val==subRoot->val
&&isSameTree(root->left,subRoot->left)
&&isSameTree(root->right,subRoot->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
if(root==NULL)//根节点为空,不符合题意
return false;
//分别以root的每一个节点作为根去判断是否root中是否有subRoot子树
return isSameTree(root,subRoot)
||isSubtree(root->left,subRoot)
||isSubtree(root->right,subRoot);
}
二叉树遍历
题目链接:牛客网KY11.二叉树遍历
题目:
题目分析:
题解:
#include<stdio.h>
typedef struct BinaryTree
{
char data; //数据域 - 用于存储数据
struct BinaryTree*left; //左指针
struct BinaryTree*right; //右指针
}BTNode;
//按照先序遍历构建一棵二叉树
BTNode* CreatTree(char*a,int*i)
{
if(a[(*i)]=='#')//如果是'#',表示这里没有数据
{
(*i)++;//对于下标向下加1
return NULL;
}
BTNode* root=(BTNode*)malloc(sizeof(BTNode));//向内存申请一个结构体大小的空间
root->data=a[(*i)++];//将数据存入二叉树中
root->left=CreatTree(a, i);//递归遍历左子树
root->right=CreatTree(a, i);//递归遍历右子树
return root;//返回构建好的二叉树根节点
}
//中序遍历 - 左子树 根 右子树
void InOrder(BTNode*root)
{
if(root==NULL)
return;
InOrder(root->left);
printf("%c ",root->data);
InOrder(root->right);
}
int main()
{
char a[100]="";//用于存储输入的字符数组
scanf("%s",a);
int i=0;//用于遍历字符数组
BTNode* tree=CreatTree(a,&i);//这里需要传变量i的地址
InOrder(tree);
return 0;
}