二叉树习题讲解(对称,翻转,子树,还原)

感谢各位大佬的光临,希望和大家一起进步,望得到你的三连,互三支持,一起进步

个人主页LaNzikinh-CSDN博客

收入专栏:初阶数据结构_LaNzikinh篮子的博客-CSDN博客

文章目录

  • 一.对称二叉树
  • 二.翻转二叉树
  • 三.判断子树
  • 四.还原二叉树
  • 总结

一.对称二叉树. - 力扣(LeetCode)

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:

输入:root = [1,2,2,3,4,4,3]
输出:true

解题思路:
判断一个树是否对称,首先要判断左右孩子是否对称相等,还需要判断左孩子的左子树是否和右孩子的右子树对称,左孩子的右子树是否和右孩子的左子树对称。

其实就是根和根比,左子数和右子数比右子数和左子数去比,开始进行空的判断,然后利用地归左右根比较,根与根要一样,左等于右右等于左,就可以了。

bool _isSymmetric(struct TreeNode* left, struct TreeNode* right)
{
    if (left == NULL && right == NULL)
        return true;
    if (left == NULL || right == NULL)
        return false;
    return left->val == right->val
        && _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 ,翻转这棵二叉树,并返回其根节点。

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

解题思路:
翻转每一棵树的左右子树根节点

二叉树的翻转,我才开始想的是用层序遍历来解,应该是可解的,但是有点复杂,我也没想了,设一个值保存树的左子树,右子树去覆盖左子树,在把右赋值给,这样就完成了一次翻转,然后在递归遍历左右就可以了,其实很简单,但是当时没有想到,注意细节,这里是翻转的结点不是值,所以原来的只会跟着过来,所以为什么后面递归遍历可以走的通

void _invertTree(struct TreeNode* root)
{
    if (root) 
    {
    
        struct TreeNode* tmp = root->left;
        root->left = root->right;
        root->right = tmp;
        _invertTree(root->left);
        _invertTree(root->right);
    }
}

struct TreeNode* invertTree(struct TreeNode* root) {
    _invertTree(root);
    return root;
}​

三.判断子树

572. 另一棵树的子树 - 力扣(LeetCode)

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1:

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

解题思路:
判断t是否为s的子树,需要判断t是否和s的某一个子树相同,所以此题就是判断两棵树是否相同的逻辑。

判断子树问题我们先要知道如何判断两个树相等,知道如何判断两棵树相等子树问题就好判断了,那么如何判断呢?思路:两个节点都为空就相等,其中一个为空另一个不为空就不相等,如果没有空,就看树里面的值,如果值不一样的话就不相等,一样的话就继续递归左右,那我判断子树的话,就只需要根据节点来判断就可以了,把这棵树遍历一遍,每一个节点和子树来比前题是节点树里的值必须和子树相等

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;
    if (root->val == subRoot->val && isSameTree(root, subRoot))
        return true;
    return  isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}

四.还原二叉树

给定一棵二叉树的前序遍历序列和中序遍历序列,要求计算该二叉树的高度。

输入格式:

输入首先给出正整数 n(≤50),为树中结点总数。随后 2 行先后给出前序和中序遍历序列,均是长度为 n 的不包含重复英文字母(区别大小写)的字符串。

输出格式:

输出为一个整数,即该二叉树的高度。

输入样例:

9
ABDFGHIEC
FDHGIBEAC

输出样例:

5

还原二叉树,就是已知一个前序或后序和一个中序来把一棵二叉树还原,那为什么是前序或后序加一个中序而不是前序和后序了,因为前和后只能确定根节点,无法知道根节点的位置,只有中序可以知道根节点的位置

思路:首先判断是否为空,如果是长度为0肯定返回空,如果长度不为零的话,先开辟一个节点,把根结点存进去,然后再中序中找到根结点的位置,然后再递归左右区间

注意:为什么左是Pre + 1, In, i,右是Pre + i + 1, In + i + 1, len - i - 1

Pre + 1是找下一个根,因为是前序遍历,根左子树右子树,In, i是因为在前一个中序中已经找到了位置,所以下一个左子树的根肯定在0到i中,Pre + i + 1是找右边的根,In + i + 1是确实右边的根在中序中的位置,len - i - 1还剩多少长度。

#define _CRT_SECURE_NO_WARNINGS 1;
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define MAX 51

typedef struct BinTree
{
	char Data;
	struct BinTree*left; //左子树
	struct BinTree*right; //右子树
}TreeNode;

TreeNode* Recover(char Pre[MAX], char In[MAX], int len) //建立二叉树 
{
	TreeNode* tmp;
	int i=0;
	if (len==0)
	{
		return NULL;
	}
	else
	{
		//存放根结点
		tmp = (TreeNode*)malloc(sizeof(TreeNode));
		assert(tmp);
		tmp->Data = Pre[0]; 
		//确定根结点在中序中的位置
		for (i = 0; i < len; i++)  
		{
			if (Pre[0] == In[i])
				break;
		}
		tmp->left = Recover(Pre + 1, In, i);
		tmp->right = Recover(Pre + i + 1, In + i + 1, len - i - 1);
	}

	return tmp;
}

int maxDepth(TreeNode* tree)
{
	if (tree == NULL)
		return 0;
	int leftDepth = maxDepth(tree->left);
	int rightDepth = maxDepth(tree->right);
	return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
			
}
int main()
{
	TreeNode* Tree;
	char xianxu[MAX] = { 0 };
	char zhongxu[MAX] = { 0 };
	int N = 0;
	int H = 0;

	scanf("%d", &N);
	scanf("%s%s", xianxu, zhongxu);
	Tree = Recover(xianxu, zhongxu, N);
	H = maxDepth(Tree);
	printf("%d\n", H);
	return 0;
}

总结

补充了一些关于二叉树的习题,和自己的一些做题经验。

  • 107
    点赞
  • 88
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 75
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 75
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LaNzikinh篮子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值