Pseudo-completeness(前中序遍历确定后序遍历)

题目链接:题目详情 - 7-16 Pseudo-completeness (pintia.cn)

样例1输入: 

7
4 2 5 1 6 3 7
1 2 4 5 3 6 7

样例1输出:

1
4 5 2 6 7 3 1

样例2输入:

10
8 4 9 2 10 5 1 6 3 7
1 2 4 8 9 5 10 3 6 7

样例2输出:

2
8 9 4 10 5 2 6 7 3 1

样例3输入:

10
8 4 2 5 11 1 6 3 14 7
1 2 4 8 5 11 3 6 7 14

样例3输出:

3
8 4 11 5 2 6 14 7 3 1

题目翻译:

在计算机科学中,“完美二叉树”(perfect binary tree)是指,二叉树的所有非叶结点都有两个孩子结点,且所有叶结点的深度相同。“完全二叉树”(complete binary tree)是指,二叉树中除了最后一层外,其他层都被填满,并且最后一层的所有结点都尽可能地靠左边。若一棵二叉树,最后一层被移除后就变成“完美二叉树”,则这棵二叉树就是“伪完全二叉树”(pseudo-complete binary tree)。

给定一棵二叉树的中序和前序遍历序列,请你判断这棵树的类型,并输出它的后序遍历序列。

输入格式:
每个输入文件包含一个测试用例。第一行是正整数N(≤2000),表示树中结点数量。接下来两行分别是中序和前序遍历序列。题目保证结点值各不相同且均在int型范围。输入的数由空格间隔。

输出格式:
第一行输出所输入树的类型:1为完美二叉树,2为完全二叉树(但不是类型1),3为伪完全二叉树(但不是类型1和2),0为其他类型的二叉树。第二行输出后序遍历序列,以空格间隔,且行首和行末没有多余的空格。

分析:这个题目的第一步还是很显然的,就是根据二叉树的前序遍历和中序遍历确定树的结构,至于最后输出树的后续遍历也是很简单的。下面主要分析一下如何判断是哪一种类型。

我们可以按照完美二叉树的标准来对树进行编号,然后我们可以遍历一遍树,记录所有节点中的最大编号,如果最大编号不等于节点个数n,那么他一定不可能是完美二叉树或者完全二叉树,等于n的话一定是完全二叉树,而完美二叉树的节点个数一定是2的某幂次-1,根据这个再做进一步判断即可。我们在搜索树的时候可以加入一个参数记录当前节点的深度,首先如果要是该树属于三种类型中的一个,那么层数显然是(int)log2(n)+1,这是显然的,那么如果某个节点的层数大于这个值,那么显然是不属于三种类型的,可以直接返回0.最后我们就需要判断一下该树是否是伪二叉树,这个的话根据定义判断即可,就是去掉最后一层节点后判断剩余节点是否是完美二叉树即可,那么就需要我们统计一下最后一层的节点个数,完美二叉树的一个特征就是节点数等于2的某幂次-1,我们利用这个特征即可判断该树是否是伪完全二叉树。最后按照题意依次输出即可。

细节见代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
const int N=1e5+10;
int a[N],b[N],l[N],r[N],mp[N];
int c[N],idx;//用来存储后序遍历序列 
vector<int> alls;
int find(int x)
{
	return lower_bound(alls.begin(),alls.end(),x)-alls.begin()+1;
}
int build(int l1,int r1,int l2,int r2)//建树 
{
	if(l1==r1) return a[l1];
	if(l1+1+(mp[a[l1]]-1-l2)>=l1+1)
		l[a[l1]]=build(l1+1,l1+1+(mp[a[l1]]-1-l2),l2,mp[a[l1]]-1);
	if(r1>=l1+1+(mp[a[l1]]-1-l2)+1)
		r[a[l1]]=build(l1+1+(mp[a[l1]]-1-l2)+1,r1,mp[a[l1]]+1,r2);
	return a[l1];
}
bool flag1=true,flag2=true,flag3=true;
int mxid=1,n;
int cnt;//统计最后一层节点的个数 
void check(int x,int h,int id)//判断树的类型
{
	mxid=max(mxid,id);
	if(h>(int)log2(n)+1)
	{
		flag1=false;
		flag2=false;
		flag3=false;
		return ;//已经确定类型是0了,继续搜索已经没有意义了 
	}
	if(h==(int)log2(n)+1) cnt++; 
	if(l[x]&&r[x])//左右子树都有 
	{
		check(l[x],h+1,id<<1);
		check(r[x],h+1,id<<1|1);
	}
	else if(l[x])//只有左子树
		check(l[x],h+1,id<<1);
	else if(r[x])
		check(r[x],h+1,id<<1|1);
	return ;
}
void show(int x)//输出后序遍历 
{
	if(l[x]) show(l[x]);
	if(r[x]) show(r[x]);
	c[++idx]=x;
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		scanf("%d",&b[i]),alls.push_back(b[i]);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	sort(alls.begin(),alls.end());//离散化 
	alls.erase(unique(alls.begin(),alls.end()),alls.end());
	for(int i=1;i<=n;i++)
	{
		a[i]=find(a[i]);
		b[i]=find(b[i]);
		mp[b[i]]=i;
	}
	int root=build(1,n,1,n);
	check(root,1,1);
	int t=1;
	while(t<=n) t<<=1;
	if(n+1!=t) flag1=false;//完全二叉树的结点个数一定是2的幂次-1 
	if(mxid!=n) flag1=flag2=false;
	if(n-cnt!=(t>>1)-1) flag3=false;
	if(flag1) puts("1");
	else if(flag2) puts("2");
	else if(flag3) puts("3");
	else puts("0");
	show(root);
	for(int i=1;i<=n;i++)
	{
		printf("%d",alls[c[i]-1]);
		if(i!=n) printf(" ");
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/3838.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

启动容器(后台模式)

使用以下命令创建一个以进程方式运行的容器 rootLAPTOP-B38J348H:~# docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world ; sleep 1; done" 在输出中&#xff0c;我们没有看到期望的 "hello world"&#xff0c;而是一串长字符 f7…

IDEA的全新UI可以在配置里启用了,快来试试吧!

刚看到IDEA官方昨天发了这样一条推&#xff1a;IDEA的新UI可以在2022.3版本上直接使用了&#xff01;开启方法如下&#xff1a;打开IDEA的Setting界面&#xff0c;在Appearance & Behavior下有个被标注为Beta标签的New UI菜单&#xff0c;具体如下图&#xff1a;勾选Enable…

ChartGPT多重插补法 填充缺失点

问题描述已知时间戳与对应的值&#xff0c;需要根据时间戳找到缺失的点&#xff0c;然后进行值的填充。例如&#xff1a;源码<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-math3 --><dependency><groupId>org.apache.commons</gr…

【微信小程序】-- uni-app 项目-- 配置 tabBar 效果(五十一)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…

【C++进阶】智能指针

文章目录为什么需要智能指针&#xff1f;内存泄漏什么是内存泄漏&#xff0c;内存泄漏的危害内存泄漏分类&#xff08;了解&#xff09;如何避免内存泄漏智能指针的使用及原理smart_ptrauto_ptrunique_ptrshared_ptr线程安全的解决循环引用weak_ptr删除器为什么需要智能指针&am…

HJZS电源监视继电器HJZS-E202 AC220V

系列型号&#xff1a; HJZS-E202断电延时继电器 HJZS-E002断电延时继电器 一 应用 HJZS-E202电源监视继电器用于直流或交流操作的各种保护和自动控制的装置中&#xff0c;用以增加触点数量。 二 安装结构 导轨安装9壳体结构&#xff0c;具体尺寸参阅外型尺寸图。 三 产品型号…

蓝桥杯刷题冲刺 | 倒计时14天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.最长递增2.走迷宫3.解立方根4.回文特判5.修改数组1.最长递增 题目 链接&#xff1a; 最长递增…

【Java版oj 】 day17杨辉三角形的变形、计算某字符出现次数

目录 一、杨辉三角形的变形 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代码 二、计算某字符出现次数 &#xff08;1&#xff09;原题再现 &#xff08;2&#xff09;问题分析 &#xff08;3&#xff09;完整代…

Python调用GPT3.5接口的最新方法

GPT3.5接口调用方法主要包括openai安装、api_requestor.py替换、接口调用、示例程序说明四个部分。 1 openai安装 Python openai库可直接通过pip install openai安装。如果已经安装openai&#xff0c;但是后续提示找不到ChatCompletion&#xff0c;那么请使用命令“pip instal…

【ArcGIS Pro二次开发】(18):地理处理工具类【Geoprocessing】补遗

ArcGIS Pro SDK 3.0中的Geoprocessing类是用于执行地理处理工具的核心类。地理处理工具是用于执行空间分析、数据转换、数据管理等任务的工具集&#xff0c;包括常见的空间分析工具、栅格处理工具、矢量处理工具、地图制图工具等。 之前有简单记录了下Geoprocessing工具的用法…

整理了一份github上比较热门的ChatGPT项目,值得收藏

ChatGPT已经火了一段时间了&#xff0c;但是&#xff0c;热度依旧是各大自媒体的热榜。由于&#xff0c;国内不能直接访问ChatGPT,国内的开发者依托OpenAI的接口&#xff0c;开发出一些ChatGPT的应用。今天就整理一下github上最热门的ChatGPT项目。 lencx/ChatGPT 该项目是Cha…

springboot校友社交系统

050-springboot校友社交系统演示录像开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;e…

蓝桥杯第14天(Python版)

并查集的使用# 并查集模板 N400 fa[] def init(): # 初始化&#xff0c;默认自身为根接点for i in range(N):fa.append(i)def merge(x,y): # 发现可以合并&#xff0c;默认选x的根节点为根接点fa[find(x)]find(y)def find(x): # 相等就是根结点&#xff0c;不然就递归查找根…

Vue3监听器使用

watch(监听的对象或值, 回调函数&#xff08;参数新值&#xff0c;旧值&#xff09;, 配置项是对象{ immediate: true//立即监听--进入就会执行一次 deep&#xff1a;true //深度监听 }) 首先引入 import { ref, watch } from vue; 设置响应式数据 const num ref(1) …

【数据结构篇C++实现】- 栈

文章目录&#x1f680;一、栈的原理精讲&#x1f680;二、栈的算法实现⛳栈的顺序存储结构&#x1f389;&#xff08;一&#xff09;顺序栈1.栈的结构体定义2.栈的初始化3.判断空栈4.判断栈满5.元素入栈6.元素出栈7.获取栈顶元素&#x1f389;&#xff08;二&#xff09;共享栈…

冯诺依曼,操作系统以及进程概念

文章目录一.冯诺依曼体系结构二.操作系统&#xff08;operator system&#xff09;三.系统调用和库函数四.进程1.进程控制块&#xff08;PCB&#xff09;2.查看进程3.系统相关的调用4.fork介绍&#xff08;并发引入&#xff09;五.总结一.冯诺依曼体系结构 计算机大体可以说是…

MD5加密竟然不安全,应届生表示无法理解?

前言 近日公司的一个应届生问我&#xff0c;他做的一个毕业设计密码是MD5加密存储的&#xff0c;为什么密码我帮他调试的时候&#xff0c;我能猜出来明文是什么&#xff1f; 第六感&#xff0c;是后端研发的第六感&#xff01; 正文 示例&#xff0c;有个系统&#xff0c;前…

【深度强化学习】(6) PPO 模型解析,附Pytorch完整代码

大家好&#xff0c;今天和各位分享一下深度强化学习中的近端策略优化算法&#xff08;proximal policy optimization&#xff0c;PPO&#xff09;&#xff0c;并借助 OpenAI 的 gym 环境完成一个小案例&#xff0c;完整代码可以从我的 GitHub 中获得&#xff1a; https://gith…

泰克信号发生器特点

泰克信号发生器是一种用于产生各种类型的电子信号的仪器&#xff0c;可以广泛应用于电子、通信、自动化、医疗等领域。泰克信号发生器具有以下特点&#xff1a;多种信号类型&#xff1a;泰克信号发生器可以产生多种类型的电子信号&#xff0c;包括正弦波、方波、三角波、脉冲等…

TitanIDE:云原生开发到底强在哪里?

原文作者&#xff1a;行云创新技术总监 邓冰寒 引言 是一种新的软件开发方法&#xff0c;旨在构建更可靠、高效、弹性、安全和可扩展的应用程序。与传统的应用程序开发方式不同&#xff0c;云原生是将开发环境完全搬到云端&#xff0c;构建一站式的云原生开发环境。云原生的开…
最新文章