洛谷P5018 对称二叉树
不多扯题目 直接题解= =
1.递归
由题目可以得知,子树既可以是根节点和叶节点组成,也可以是一个节点,题意中的对称二叉子树是必须由一个根节点一直到树的最底部所组成的树。
这样一来就简单了,我们很容易就能想到用递归的方法
1.枚举根节点,判断其左右两个孩子节点 是否存在
以及是否相等
. 若存在并且点权相等,则一直递归左右两个孩子节点
的左右两个孩子节点
.
重复上述判断。
2.判断好对称二叉树后,就可以计算以该节点为根节点的对称二叉子树的节点数量并取最优值了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define N 1e6 + 10;//习惯性用定义法 当然也可以用const int v[N], l[N], r[N]; //v[i]:节点i权值;l[i]:编号为i的节点的左孩子的编号;r[i]:编号为i的节点的右孩子的编号 int n,ans = 0; bool pd; //判断是否为对称二叉子树 int cnt(int x) { //计算以x为根节点的对称二叉子树的节点数 int sum 0; if (l[x]!=-1) sum+=cnt(l[x]); if (r[x]!=-1) sum+=cnt(r[x]); return sum+1; //算上根节点 } void check(int x, int y) { //判断对称二叉子树 if (x==-1&&y==-1) return ; //到底了 结束 if (x==-1||y==-1||v[x]!=v[y]) { //不对称 pd = false; return; } check(l[x], r[y]); check(r[x], l[y]); } int main() { cin>>n; for (int i=1;i<=n;++i) cin>>v[i]; for (int i=1;i<=n;++i) cin>>l[i]>>r[i]; ans = 1; //至少有一个对称(一个节点) for(int i=1; i<=n;++i) {//枚举对称二叉子树的根节点 if (l[i]!=-1&&r[i]!=-1&&v[l[i]]==v[r[i]]){ pd=true; //先默认为是对称二叉子树 check(l[i], r[i]); if (pd) ans=max(ans, cnt(i)); //如果是对称二叉子树就可以计算节点数取最大值了 } } cout<<ans; return 0; }
check(l[x],r[y]);
check(r[x],l[y]);
判断对称二叉子树时,应该是镜面对称的
所以在check时直接镜面对称即可
2dfs
如果一个二叉树是对称的,那么对于深度相同的两个节点u,v,必定有lson(u)lson(u)与rson(v)rson(v),rson(u)rson(u)与lson(v)lson(v),并且val_u=val_v:
int read()
{
int x=0,f=1;
char ch=getchar();
while('0'>ch||'9'<ch){
if (ch=='-')
f=-1;
ch=getchar();
}//判断正负
while('0'<=ch<='9'){
x=x*10+ch-48;
ch=getchar();
}//纯数字相加
return x*f;
}
int n,son[1000050][2],val[1000050],size[1000050];
//son[i][0]为i的左儿子
//son[i][1]为i的右儿子
void dfs(int u) //分别从左右扫一遍
{
size[u]=1;
if(son[u][0]!=-1)
{
dfs(son[u][0]);
size[u]+=size[son[u][0]];//size进入下一步dfs前先把当前状态改变
}
if (son[u][1]!=-1)
{
dfs(son[u][1]);
size[u]+=size[son[u][1]];
}
}
bool check(int u,int v)
{
if (u==-1&&v==-1)//特判
return true;
if (u!=-1&&v!=-1&&val[u]==val[v]&&check(son[u][0],son[v][1])&&check(son[u][1],son[v][0]))
return true;
return false;
}
int main()
{
n=read();
for (int i=1;i<=n;i++)
val[i]=read();
for (int i=1;i<=n;i++)
{
son[i][0]=read();
son[i][1]=read();
}
dfs(1);
int ans=0;
for (int i=1;i<=n;i++)
if(check(son[i][0],son[i][1]))
ans=max(ans,size[i]);
cout<<ans<<endl;
return 0;
}
然而我觉得这个近乎爆搜的打法还不如递归好使而且对我来说还挺难想= =
3.hash
可以直接hash树的形态,即分中序遍历1(先进左子树)和中序遍历2(先进右子树)记录hash值,对于每一个节点,若是此节点的左儿子的中序遍历1的hash值等于右儿子的中序遍历2的hash值,说明这个点为根的树是对称的(然而我用递归通过的= =所以hash就没打代码= =)
原文地址:https://www.cnblogs.com/SKTskyking/p/12721744.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Mybatis-Plus代码生成器
- RabbitMQ入门教程
- 使用 Django + Vue.js 开发个人博客网站(完整版附源码)—— Python-课程设计-期末项目
- LVM添加硬盘并扩容至已有分区
- 新增项目时如何修改Jenkins
- 使用封锁协议解决事务的并发问题
- 命令小技巧总结
- Java 中 HashMap 数据结构分析(语言无关)
- Java8中日期的特性,别再用Date来处理日期啦~
- 数据库系统概论考试心得+复习指南
- Docker的基础知识和简单应用
- Spring 注解开发之 @ComponentScan
- 事务并发调度的可串行性及两段锁协议
- 面试不易,控场情况下,感觉少要了1万!
- Java 操作 ElasticSearch