目录
二叉树OJ练习
单值二叉树
思路
实现
检查两颗树是否相同
思路
实现
对称二叉树
思路
实现
二叉树的前序遍历
思路
实现
二叉树中序遍历
思路
实现
二叉树的后序遍历
思路
实现
另一颗树的子树
思路
实现
力扣965. 单值二叉树
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true
;否则返回 false
。
提示:
[1, 100]
。[0, 99]
。思路
首先判断整个树的节点的值是否相等,可以将整个二叉树拆分成多个子树,每个子树只需要堆根节点,左子节点,右子节点进行比较,相等关系的比较可以间接获得,如a=b,a=c可以推断a=c。因此每个子树只要根节点的值等于左节点的值,根节点的值等于右节点的值,整个子树就是单值子树。
其次二叉树中可能出现空节点的情况(题目中祖先节点必不为空,所以不考虑组先节点),简化如下:
当节点为空时,不需要判断,所以判断之前要子节点先进行不为空判断,然后再判断值。
最后时返回值,
返回分为三个部分。
一、不相等时返回:整个题目中如果出现一次判断不相等,后续的程序不需要进行,所以不相等时返回false,如果相等则继续递归。
二、相等时返回:相等时需要继续向下递归,直到递归完整棵树,所以当子树的根节点为空时说明被判断过的子树的值完全相等。
三、左子树与右子树的值是否相等,递归时一次只能递归一棵子树,所以最终的结果需要左子树与右子树的结果逻辑与之后才能判断。
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool isUnivalTree(struct TreeNode* root)
{
if(root==NULL)
return true;
if(root->left!=NULL&&root->val!=root->left->val)
return false;
if(root->right!=NULL&&root->val!=root->right->val)
return false;
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}
力扣https://leetcode.cn/problems/same-tree/
给你两棵二叉树的根节点 p
和 q
,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
提示:
[0, 100]
内-104 <= Node.val <= 104
思路
判断是否相同的两棵树需要从两个方面判断值与结构,简化如下:
同样的将整个二叉树划分为由根节点,左子树,右子树组成的子树,当两个子树之间结构相等,值相等时两个子树完全相等。
对子树的判断本质上也是对根节点的判断,当根节点相等时才会继续判断左子树的节点,左子树的节点完全相同时判断右子树的节点,左右子树的节点本身也可以看作根节点,所以只需要化简为对根节点的判断。
判断的过程,程序递归判断,相同时继续递归直到节点为空说明所遍历过的节点相等,可以返回真值,如果不同则返回假。
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
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);
}
101. 对称二叉树
给你一个二叉树的根节点 root
, 检查它是否轴对称。
思路
根据题目的意思,组先节点不用判断,因此判断一个数是否对称,可以理解为判断两个数是否为镜像。
对称的判断需要对值和结构进行判断:
值的判断:
P树的左根节点的值等于Q树的右根节点的值,两者相等。
结构的判断:
P,Q同时为空或者同时不为空时两者结构相等,P为空Q不为空或者相反时,两者结构不相等。
子树完全相等返回值:
P,Q递归到空时,说明之前的节点相等,因此返回true,其余的情况返回false。
实现
为了避开对祖先节点的影响,所以另写一个函数对子树进行判断。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool isTree(struct TreeNode* p,struct TreeNode* q)
{
if(p==NULL&&q==NULL)
{
return true;
}
if(p==NULL||q==NULL)
{
return false;
}
if(p!=NULL&&q!=NULL&&p->val!=q->val)
{
return false;
}
return isTree(p->left,q->right)&&isTree(p->right,q->left);
}
bool isSymmetric(struct TreeNode* root)
{
return isTree(root->left,root->right);
}
144. 二叉树的前序遍历
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
思路
本题目要求用前序遍历的顺序将二叉树中节点的值放在数组中返回,因为数组的大小不确定,所以需要先遍历二叉树的节点确定数组的大小,或者直接开辟超大数组也可以(不过这样有点浪费)。开辟数组后,前序遍历二叉树,当二叉树节点不为空时,把值放入数组,为空时返回,需要注意传递数组下标时不能使用传值方式,必须使用传址的方式。
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int preorderOrder(struct TreeNode* root)
{
if(root==NULL)
{
return 0;
}
return 1+preorderOrder(root->left)+preorderOrder(root->right);
}
void preorder(struct TreeNode* root,int* capacity,int *returnSize)
{
if(root==NULL)
{
return ;
}
capacity[*returnSize]=root->val;
(*returnSize)++;
preorder(root->left,capacity,returnSize);
preorder(root->right,capacity,returnSize);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize)
{
*returnSize=0;
int num=preorderOrder(root);
int *capacity=(int *)malloc(sizeof(int)*num);
assert(capacity);
preorder(root,capacity,returnSize);
return capacity;
}
94. 二叉树的中序遍历
思路
与前序一样。
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int preorderOrder(struct TreeNode* root)
{
if(root==NULL)
{
return 0;
}
return 1+preorderOrder(root->left)+preorderOrder(root->right);
}
void inorder(struct TreeNode* root,int* capacity,int *returnSize)
{
if(root==NULL)
{
return ;
}
inorder(root->left,capacity,returnSize);
capacity[*returnSize]=root->val;
(*returnSize)++;
inorder(root->right,capacity,returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize)
{
*returnSize=0;
int num=preorderOrder(root);
int *capacity=(int *)malloc(sizeof(int)*num);
assert(capacity);
inorder(root,capacity,returnSize);
return capacity;
}
思路
与前序,中序相同。
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int preorderOrder(struct TreeNode* root)
{
if(root==NULL)
{
return 0;
}
return 1+preorderOrder(root->left)+preorderOrder(root->right);
}
void postorder(struct TreeNode* root,int* capacity,int *returnSize)
{
if(root==NULL)
{
return ;
}
postorder(root->left,capacity,returnSize);
postorder(root->right,capacity,returnSize);
capacity[*returnSize]=root->val;
(*returnSize)++;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize)
{
*returnSize=0;
int num=preorderOrder(root);
int *capacity=(int *)malloc(sizeof(int)*num);
assert(capacity);
postorder(root,capacity,returnSize);
return capacity;
}
572. 另一棵树的子树
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subtree-of-another-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
判断另一棵树与子树相等,本质上时对两棵树的判断,因此需要将整个问题拆分成两部分,一是对两棵树的判断,二是递归新的子树与另一棵树判断。
对两棵树的判断可以参考前面对两个数判断的题目,这里主要说明传递新树的部分:
传递新树本质是传递根节点,因此传递新数可以采用递归左子树与递归右子树的方式,如果相同返回真,如果不同继续递归新的节点,该题目中真是唯一确认的条件,因此当传递的根节点为空时,说明没有找到相同的子树,所以返回假。同时题目需要对两颗子树进行判断,所以最终的结果时左子树与右子树判断的结果逻辑或(利用逻辑或短路运算的优势,如果左子树为真则不需要判断右子树)。
实现
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool issametree(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 issametree(root->left,subRoot->left)&&issametree(root->right,subRoot->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
if(root==NULL)
{
return false;
}
if(issametree(root,subRoot))
{
return true;
}
else
{
return isSubtree(root->left, subRoot)||isSubtree(root->right, subRoot);
}
}