[GESP202606 六级] 满二叉树

视频讲解:GESP202606 六级 满二叉树-信息学奥赛GESP等级考试真题解析

一、原题

题目描述

给定一棵包含 n 个结点的有根二叉树,结点依次以 1,2,...,n 编号,根结点编号为 1。

对于结点 i,其左儿子的编号记为 li​,右儿子编号记为 ri​。特别地,如果左儿子不存在则 li​=0,如果右儿子不存在则 ri​=0。

树中每个结点都对应一棵以其为根的子树。请你求出给定有根树的所有 n 棵子树中,有多少棵子树是满二叉树。

满二叉树是指所有叶子深度均相同,且除叶子外均有两个儿子的二叉树,例如以下三棵二叉树均是满二叉树:

复制代码
()   ()        ()
    /  \      /  \
   ()  ()   ()    ()
           /  \  /  \
          ()  ()()  ()

在上面这棵有 3 个节点的二叉树中,有 3 个子树是满二叉树(包括整个树本身,及所有的单个叶子节点);

又例如,

复制代码
   (1)
   / \
 (2) (3)
     / \
   (4) (5)

在上面这棵有 5 个节点的二叉树中,有 4 个子树是满二叉树(包括节点 3 的子树,以及所有单个叶子节点)。

输入格式

第一行,一个正整数 n,表示有根二叉树结点数量。

接下来 n 行,每行两个非负整数 li​,ri​,表示结点 i 的左儿子编号和右儿子编号,整数之间以空格分隔。

输出格式

输出一行,一个整数,表示所有子树中满二叉树的数量。

输入输出样例

输入 #1

复制代码
4
2 3
4 0
0 0
0 0

输出 #1

复制代码
23

输入 #2

复制代码
3
2 3
0 0
0 0

输出 #2

复制代码
3

说明/提示

数据范围

对于 40% 的测试点,保证 1≤n≤500。

对于所有测试点,保证 1≤n≤10^5。

二、做题思路

1)二维数组构造二叉树

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int tree[100005][2]; 
int main(){
	//1)二维数组构造二叉树
	//1.1)确定结点数量n
	int n;cin>>n;
	//1.2)填充每个结点左右子树
	for(int i=1;i<=n;i++)
		cin>>tree[i][0]>>tree[i][1];
} 

2)深搜每一个结点

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int tree[100005][2];
void dfs(int x){
	//2.2)子树不为空,就向下搜索
	if(tree[x][0]!=0) dfs(tree[x][0]);
	if(tree[x][1]!=0) dfs(tree[x][1]);
}
int main(){
	//1)二维数组构造二叉树
	//...
	//2)深搜每一个结点
	//2.1)深搜函数,从1开始 
	dfs(1);
} 

3)判断是否为满二叉树

3.1)叶子节点是满二叉 ,高度为1

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int tree[100005][2];
int d[100005];
bool m[100005]; 
void dfs(int x){
	//3)判断是否为满二叉树
	//3.1)叶子节点是满二叉 ,高度为1
	if(!tree[x][0]&&!tree[x][1]){//左右为空是叶子节点 
		m[x]=d[x]=1;
		return ;
	}
	//2.2)子树不为空,就向下搜索
	//...
}
int main(){
	//1)二维数组构造二叉树
	//...
	//2)深搜每一个结点
	//2.1)深搜函数,从1开始 
	dfs(1);
} 

3.2)满二叉条件:左右高度相同,左右都是满二叉

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int tree[100005][2];
int d[100005];
bool m[100005]; 
void dfs(int x){
	//3)判断是否为满二叉树
	//3.1)叶子节点是满二叉 ,高度为1
	//...
	//2.2)子树不为空,就向下搜索
	//...
	//3.2)满二叉条件:左右高度相同,左右都是满二叉
	if(d[tree[x][0]]==d[tree[x][1]]&&m[tree[x][0]]&&m[tree[x][1]]){
		m[x]=1;
		d[x]=max(d[tree[x][0]],d[tree[x][1]])+1;
	}
}
int main(){
	//1)二维数组构造二叉树
	//...
	//2)深搜每一个结点
	//2.1)深搜函数,从1开始 
	dfs(1);
} 

4)计算满二叉数量

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int tree[100005][2];
int d[100005];
bool m[100005]; 
void dfs(int x){
	//3)判断是否为满二叉树
	//3.1)叶子节点是满二叉 ,高度为1
	//...
	//2.2)子树不为空,就向下搜索
	//...
	//3.2)满二叉条件:左右高度相同,左右都是满二叉
	//...
}
int main(){
	//1)二维数组构造二叉树
	//...
	//2)深搜每一个结点
	//2.1)深搜函数,从1开始 
	dfs(1);
	//4)计算满二叉数量
	int ans=0;
	for(int i=1;i<=n;i++) if(m[i]) ans++;
	cout<<ans;
} 

三、答案

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int tree[100005][2];
int d[100005];
bool m[100005];
void dfs(int x){
	//3)判断是否为满二叉树
	//3.1)叶子节点是满二叉 ,高度为1
	if(!tree[x][0]&&!tree[x][1]){//左右为空是叶子节点 
		m[x]=d[x]=1;
		return ;
	}
	//2.2)子树不为空,就向下搜索
	if(tree[x][0]!=0) dfs(tree[x][0]);
	if(tree[x][1]!=0) dfs(tree[x][1]);
	//3.2)满二叉条件:左右高度相同,左右都是满二叉
	if(d[tree[x][0]]==d[tree[x][1]]&&m[tree[x][0]]&&m[tree[x][1]]){
		m[x]=1;
		d[x]=max(d[tree[x][0]],d[tree[x][1]])+1;
	}
}
int main(){
	//1)二维数组构造二叉树
	//1.1)确定结点数量n
	int n;cin>>n;
	//1.2)填充每个结点左右子树
	for(int i=1;i<=n;i++)
		cin>>tree[i][0]>>tree[i][1];
	//2)深搜每一个结点
	//2.1)深搜函数,从1开始 
	dfs(1);
	//4)计算满二叉数量
	int ans=0;
	for(int i=1;i<=n;i++) if(m[i]) ans++;
	cout<<ans;
} 
相关推荐
深圳市快瞳科技有限公司4 小时前
野外鸟类AI识别落地实录:输入适配、结构化输出、去重聚合与置信度分流的工程实践
算法·计算机视觉·鸟类识别·鸟类ai识别·野外鸟类观测·林业调查
专注仿真6 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
小豆庄6 小时前
视频遮罩追踪退场后ID撞号的排查—多目标场景下的失效
opencv·算法·bug·视频·python3.11
Tisfy6 小时前
LeetCode 3882.网格图中最小异或路径:动态规划
算法·leetcode·动态规划
D e re k ZH7 小时前
P5025 [SNOI2017] 炸弹
c++·算法
A boy CDEF girl7 小时前
算法题专栏:优选算法
数据结构·算法·leetcode
没落之王7 小时前
三易五行看宋朝的三界确立
大数据·人工智能·算法
坤坤子吖8 小时前
算法学习——单调队列
开发语言·c++·笔记·学习·算法
Js.Tx9 小时前
【具体数学 Concrete Mathematics】2.1.5 一般性的方法
算法·具体数学
秋天的怀念_David11 小时前
算法一千零一夜 · 作品相关:版权与致谢声明
程序人生·算法·学习方法