本文主要讲解一些链式二叉树的相关OJ题目
文章目录
- 1、[单值二叉树](https://leetcode.cn/problems/univalued-binary-tree/submissions/)
- 2、[检查两颗树是否相同](https://leetcode.cn/problems/same-tree/)
- 3、[对称二叉树](https://leetcode.cn/problems/symmetric-tree/submissions/)
- 4、[另一颗树的子树](https://leetcode.cn/problems/subtree-of-another-tree/)
- 5、[二叉树的构建及遍历](https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId=60&&tqId=29483&rp=1&ru=/activity/oj&qru=/ta/tsing-kaoyan/question-ranking)
- 6、[翻转二叉树](https://leetcode.cn/problems/invert-binary-tree/)
- 7、[平衡二叉树](https://leetcode.cn/problems/balanced-binary-tree/)
1、单值二叉树
思路:所有的值都相等才是单值二叉树
当左右子树都不为空的时候,将左右子树的值与根节点的值比较,全部相同则真,否则返回假
1:如果根节点为NULL,则返回true
2:如果左子树不为空,但是左子树的值和根不相同,返回false
3:如果右子树不为空,但是右子树的值和根不相同,返回false
4:继续递归左右子树比较,这里要用与,因为左右子树有一个不相同都不行
bool isUnivalTree(struct TreeNode* root)
{
if(root == NULL)
{
return true;
}
//左节点不为空,将左节点值 != 根值
if(root->left != NULL && root->left->val != root->val)
{
return false;
}
//右节点不为空,将右节点值 != 根值
if(root->right != NULL && root->right->val != root->val)
{
return false;
}
//递归下去,继续比较
return isUnivalTree(root->left) && isUnivalTree(root->right);
}
递归图解:
2、检查两颗树是否相同
思路:一个一个比较根节点的值就行了
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);
}
递归图解:
3、对称二叉树
思路:写一个子树比较的函数,因为我们的根节点是同一个,所以我们把左右子树传过去比较就行了。
首先比较两颗子树的根节点,根节点不同直接返回,根节点相同了,再去递归比较两个子树的左右节点,因为是对称,所以比较子树p的左孩子和子树q的右孩子以及子树p的右孩子和子树q的左孩子。
bool _isSymmetric(struct TreeNode* root1, struct TreeNode* root2)
{
if(root1 == NULL && root2 == NULL)
{
return true;
}
if(root1 == NULL || root2 == NULL)
{
return false;
}
if(root1->val != root2->val)
{
return false;
}
return _isSymmetric(root1->left, root2->right) && _isSymmetric(root1->right, root2->left);
}
bool isSymmetric(struct TreeNode* root)
{
if(root == NULL)
{
return true;
}
return _isSymmetric(root->left, root->right);
}
4、另一颗树的子树
思路:因为是看
subRoot
是不是root
的子树,所有从根节点比较,root
的子树一定有一颗和subRoot
相同。调用上面相同的树这个函数,将根节点传过去,如果相同就返回true,否则递归下去,传左右节点继续找。有一个满足即可
//比较两个数是否相同
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;
}
//如果根节点开始的树和subRoot相同
if( isSameTree(root, subRoot))
{
return true;
}
//不相同,递归根节点的左子树和根节点的右子树查找
return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}
递归图解:
5、二叉树的构建及遍历
思路:其实就是将字符串变成链式二叉树
#include <stdio.h>
#include <stdlib.h>
struct TreeNode
{
char val;
struct TreeNode* left;
struct TreeNode* right;
};
//构造树
struct TreeNode* rebuildTree(char* str, int* pi)
{
//如果是#直接返回
if(str[*pi] == '#')
{
(*pi)++;
return NULL;
}
//不是#,则构建节点
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->val = str[(*pi)++];
//递归构建左右节点,并链接
root->left = rebuildTree(str, pi);
root->right = rebuildTree(str, pi);
return root;
}
//中序遍历
void InOrder(struct TreeNode* root)
{
if(root == NULL)
return;
InOrder(root->left);
printf("%c ",root->val);
InOrder(root->right);
}
int main()
{
char str[101];
scanf("%s",str);
int i = 0;
struct TreeNode* root = rebuildTree(str, &i);
InOrder(root);
return 0;
}
递归图解:
6、翻转二叉树
思路:从后往前依次翻转,先翻转两个子树,最后再整体翻转,先反转1和3,再翻转6,9,再翻转2和7
由于要改变节点,所以需要保存!!!!
//翻转每颗左右子树的根节点
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;
}
7、平衡二叉树
思路:首先写一个求二叉树的高度函数,然后把左右节点传过去求出高度,然后做差看看是不是大于1,大于1就为假,否则继续递归下去,再比较左右子树
//高度函数
int treeHeight(struct TreeNode* root)
{
if(root == NULL)
{
return 0;
}
int leftHeight = treeHeight(root->left);
int rightHeight = treeHeight(root->right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool isBalanced(struct TreeNode* root)
{
if(root == NULL)
{
return true;
}
int left = treeHeight(root->left); //左子树的高度
int right = treeHeight(root->right);//右子树的高度
int len = abs(left-right); //高度差
if(len>1)
{
return false;
}
return isBalanced(root->left) && isBalanced(root->right); //继续递归比较
}