题解 P5018 【对称二叉树】
其实本题的解题思路都差不多,但是要考虑清楚
程序主要部分:递归
-然而我听说这是一题水题
题目传送门
【题目解读】
看图,我们可以知道,对于题目给出的二叉树的子树中是否存在对称二叉树(当然这个子树可能是它自己),可以判断:
- 结构不对称的不是;
- 权值不对称的不是;
然后针对这两种情况写一个递归边界;
接着还要考虑:两个对称位置的孩子节点都没有自己的孩子,那么这时递归也应该停止,返回此时节点数
这里值得注意的是,这一题对称二叉树要整棵树对称,而不是子树自己对称,所以继续递归时代码要这么写:
return dfs(lchild[i],rchild[j])+dfs(lchild[j],rchild[i])+2;
最左边的孩子节点和最右边的比较,以此类推。这样才能整棵树对称,而不是局部的对称。
那么代码实现也很简单:
- 定义标志变量,以便递归时判断是否为对称二叉树
- 答案 ans 初值设为 0,搜完最后输出的时候 +1 (第一、每颗树的父节点没有算;第二、如果没有搜到符合条件的树,那么每个个叶节点都是符合条件的“对称二叉树”,所以要 +1 )
以上就是全部思路,这样代码就很容易实现了。(为什么Dalao的代码那么长)
//认真看,杜绝抄袭
#include<iostream>
#include<cstdio>
#define MAX_N 1000005
using namespace std;
int n,lchild[MAX_N],rchild[MAX_N],w[MAX_N],ans=0;
bool flag=true;
int dfs(int i,int j)
{
if(i==-1 && j==-1)
//左右孩子都没有自己的孩子了,没有接下来的节点
//此时符合题目“对称二叉树”的定义
return 0;
if((i==-1 || j==-1) && i!=j)
//左孩子和右孩子有一个没有节点 结构不对称
{
flag=false;
return 0;
}
if(w[i]!=w[j])
//权值不对称
{
flag=false;
return 0;
}
return dfs(lchild[i],rchild[j])+dfs(lchild[j],rchild[i])+2;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n;i++)
scanf("%d%d",&lchild[i],&rchild[i]);
for(int i=1;i<=n;i++)
{
int k=dfs(lchild[i],rchild[i]);//搜
if(flag)
//flag为真 说明以第i个节点为父节点找到了对称二叉树
{
ans=max(ans,k);
}
flag=true;
//重置,以便下次运算
}
printf("%d",ans+1);//结束时算上父根节点
return 0;
}
总结ing
这题考的二叉树的基本知识和递归;