写在前面
这是本蒟蒻的第二篇题解。由于作者水平不高,本题解存在有数量庞大的错误。对于题解中的错误、可优化部分,欢迎各位大佬批评指正!不合适的部分,还请多多包涵!
本题目来源于洛谷。网址https://www.luogu.com.cn/problem/P4913。
本博客非营利性,如遇侵权,请联系作者删除,谢谢!
题面
【深基16.例3】二叉树深度
题目描述
有一个 \(n(n \le 10^6)\) 个结点的二叉树。给出每个结点的两个子结点编号(均不超过 \(n\)),建立一棵二叉树(根节点的编号为 \(1\)),如果是叶子结点,则输入 0 0
。
建好这棵二叉树之后,请求出它的深度。二叉树的深度是指从根节点到叶子结点时,最多经过了几层。
输入格式
第一行一个整数 \(n\),表示结点数。
之后 \(n\) 行,第 \(i\) 行两个整数 \(l\)、\(r\),分别表示结点 \(i\) 的左右子结点编号。若 \(l=0\) 则表示无左子结点,\(r=0\) 同理。
输出格式
一个整数,表示最大结点深度。
样例 #1
样例输入 #1
7
2 7
3 6
4 5
0 0
0 0
0 0
0 0
样例输出 #1
4
题目解释
其实这题就是给定二叉树求最大深度。
先把样例转为二叉树图像:
题目中输入了"\(0\)",但因为"\(0\)"是叶结点的标志,因此形成的二叉树中不含元素"\(0\)"。
那么,“\(0\)"怎么用呢?
我们采用搜索的方式,遇“\(0\)"则返回。
注意,最关键的地方来了
整体的搜索,就是使用一种废话般的规律: 从叶结点的(虚拟的)子结点向上,每走一层长度增加\(1\)。
由于要找最大长度,所以每个结点处我们选择左右子树中较大的一个;持续比较下去,最终比较到根结点,即为结果。
代码实现
前期准备:
int n;
const int MAXN=1e6+7;
struct TreeNode//存储各结点左右子树深度
{
int left,right;//left,right分别为左右子树深度
}tree[MAXN];//表示各结点
DFS(大法师深搜)过程 (我自己都怀疑有点过短了):
int dfs(int x)//x表示被处理结点编号
{
if(x==0)//遇假设的叶结点的子结点
return 0;//返回0(从该结点向上查找,应从0开始)
return max(dfs(tree[x].left),dfs(tree[x].right))+1;//返回左右结点中深度较大的结点之深度,并加上向上查找的步骤1
}
主函数(只有输入输出……):
int main()
{
scanf("%d",&n);//输入结点数
for(int i=1;i<=n;i++)
scanf("%d%d",&tree[i].left,&tree[i].right);//输入各结点编号
printf("%d",dfs(1));//搜索并输出
return 0;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
int n;
const int MAXN=1e6+7;
struct TreeNode
{
int left,right;
}tree[MAXN];
int dfs(int x)
{
if(x==0)
return 0;
return max(dfs(tree[x].left),dfs(tree[x].right))+1;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&tree[i].left,&tree[i].right);
printf("%d",dfs(1));
return 0;
}
请注意
- 本次代码不多,但也不能大意
- 在深搜函数中的返回值一定不能有拼写错误
- 本蒟蒻使用的结构体,诸位也可根据自己喜好更换
时间复杂度
由于数据规模实在太大,所以只试了100的。循环次数为7201。
以下为洛谷运行结果:
还算可以
写在最后
这次的题解花了2小时,仍是十分不易 o(>﹏<)o
再次表示:
这是本蒟蒻的第二篇题解。由于作者水平不高,本题解存在有数量庞大的错误。对于题解中的错误、可优化部分,欢迎各位大佬批评指正!不合适的部分,还请多多包涵!
本题目来源于洛谷。网址https://www.luogu.com.cn/problem/P4913。
本博客非营利性,如遇侵权,请联系作者删除,谢谢!
最后,都看到这里了,不留个推荐吗?