题目

Given a tree, you are supposed to tell if it is a complete binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (<=20) which is the total number of nodes in the tree — and hence the nodes are numbered from 0 to N-1. Then N lines follow, each corresponds to a node, and gives the indices of the lef and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.

Output Specification:

For each case, print in one line “YES” and the index of the last node if the tree is a complete binary tree, or “NO” and the index of the root if not. There must be exactly one space separating the word and the number.

Sample Input 1:

9

7 8

– –

– –

– –

0 1

2 3

4 5

– –

– –

Sample Output 1:

YES 8

Sample Output 2:

8

– –

4 5

0 6

– –

2 3

– 7

– –

– –

Sample Output 2:

NO 1

题目分析

已知树所有节点的子节点信息,判断是否是完全二叉树,是打印YES+最后一个节点,否打印NO+根节点

解题思路

  1. 深度遍历树,将树中节点存储与数组中,根节点index=0,其左右子节点index分别为2i+1,2i+2
  2. 判断是否为完全二叉树

    2.1 方式一:判断前后节点index是否相差1(若使用数组存储判断数组中有没有浪费的空闲位置,因为完全二叉树使用数组存储时中间没有空闲位置)

    2.2 方式二:最大index==结点数n-1,若相等即为二叉树

    2.3 方式三:BFS借助队列层级遍历树,完全二叉树中间不会遇到NULL

Code

Code 01

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 30;
bool isRoot[maxn]; // 结点是否是根结点
struct Node {
int left, right; // 左孩子和右孩子的下标
} node[maxn]; // 二叉树结点静态数组
// input函数输入数据
int input() {
char id[3];
scanf("%s", id); // 输入结点编号
if(id[0] == '-') {
return -1; // 如果是'-',说明是空结点,返回-1
} else {
if(strlen(id) == 1) return id[0] - '0'; // 编号小于10
else return (id[0] - '0') * 10 + (id[1] - '0'); // 编号大于等于10
}
}
// findRoot函数找到根结点编号
int findRoot(int n) {
for(int i = 0; i < n; i++) {
if(isRoot[i]) { // isRoot为true时直接返回根结点编号i
return i;
}
}
}
// BFS函数判断完全二叉树,root为根结点编号,last是最后一个结点编号(注意引用),n为结点个数
bool BFS(int root, int &last, int n) {
queue<int> q; // 定义队列
q.push(root); // 根结点入队
while(n) { // 只要n不为0,即还没有访问完全部非空结点
int front = q.front(); // 队首结点front
q.pop(); // 弹出队首结点
if(front == -1) return false; // 访问到空结点,一定是非完全二叉树
n--; // 已访问的非空结点减少1
last = front; // 记录最后一个非空结点编号
q.push(node[front].left); // 左孩子入队(包括空结点)
q.push(node[front].right); // 右孩子入队(包括空结点)
}
return true; // 已经访问完所有非空结点,还没有碰到空结点,一定是完全二叉树
}
int main() {
int n;
scanf("%d", &n); // 输入结点个数
memset(isRoot, true, sizeof(isRoot)); //初始化所有结点都是根结点
for(int i = 0; i < n; i++) { // 对每一个结点
int left = input(), right = input(); // 输入左右孩子编号
isRoot[left] = isRoot[right] = false; // 这两个编号一定不是根结点
node[i].left = left; // 记录左孩子
node[i].right = right; // 记录右孩子
}
int root = findRoot(n), last; // 寻找根结点root,定义最后一个结点last
bool isCompleteTree = BFS(root, last, n); // 判断完全二叉树,同时记录最后一个结点last
if(isCompleteTree) { // 如果是完全二叉树
printf("YES %d\n", last); // 输出最后一个结点编号
} else {
printf("NO %d\n", root); // 否则输出根结点编号
}
return 0;
}

Code 02

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=20;
int flag[maxn];
struct node {
int data;
int index;
int left=-1;
int right=-1;
} nds[maxn];
void dfs(int root,int index) {
if(root==-1)return;
nds[root].index=index;
dfs(nds[root].left,2*index+1);
dfs(nds[root].right,2*index+2);
}
bool cmp(node &n1,node &n2){
return n1.index<n2.index;
}
int main(int argc,char * argv[]) {
int n;
scanf("%d",&n);
string f,r;
for(int i=0; i<n; i++) {
cin>>f>>r;
nds[i].data=i;
if(f!="-") {
nds[i].left=stoi(f);
flag[nds[i].left]=1;
}
if(r!="-") {
nds[i].right=stoi(r);
flag[nds[i].right]=1;
}
}
//find root;
int k=0;
while(k<n&&flag[k]==1)k++;
dfs(k,0);
sort(nds,nds+n,cmp);
/**
判断当前树是否为完全二叉树:
方式一:遍历所有节点,前后节点index相差1
方式二:完全二叉树的所有节点最大index为n
*/
bool iscbt=true;
for(int i=1; i<n; i++) {
if(nds[i].index-nds[i-1].index!=1) {
iscbt=false;
}
}
if(iscbt)printf("YES %d",nds[n-1].data);
else printf("NO %d", nds[0].data);
return 0;
}

Code 03

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=20;
int flag[maxn];
struct node {
int left=-1;
int right=-1;
} nds[maxn];
int max_n,max_i;
void dfs(int root,int index) {
if(root==-1)return;
if(max_i<index) {
max_i=index;
max_n=root;
}
dfs(nds[root].left,2*index+1);
dfs(nds[root].right,2*index+2);
}
int main(int argc,char * argv[]) {
int n;
scanf("%d",&n);
string f,r;
for(int i=0; i<n; i++) {
cin>>f>>r;
if(f!="-") {
nds[i].left=stoi(f);
flag[nds[i].left]=1;
}
if(r!="-") {
nds[i].right=stoi(r);
flag[nds[i].right]=1;
}
}
//find root;
int k=0;
while(k<n&&flag[k]==1)k++;
dfs(k,0);
/**
判断当前树是否为完全二叉树:
方式一:遍历所有节点,前后节点index相差1
方式二:完全二叉树的所有节点最大index为n
*/
if(max_i==n-1)printf("YES %d",max_n);
else printf("NO %d", k);
return 0;
}

PAT Advanced 1110 Complete Binary Tree (25) [完全⼆叉树]的更多相关文章

  1. [二叉树建树&完全二叉树判断] 1110. Complete Binary Tree (25)

    1110. Complete Binary Tree (25) Given a tree, you are supposed to tell if it is a complete binary tr ...

  2. PAT甲级——1110 Complete Binary Tree (完全二叉树)

    此文章同步发布在CSDN上:https://blog.csdn.net/weixin_44385565/article/details/90317830   1110 Complete Binary ...

  3. PAT 甲级 1110 Complete Binary Tree

    https://pintia.cn/problem-sets/994805342720868352/problems/994805359372255232 Given a tree, you are ...

  4. 1110. Complete Binary Tree (25)

    Given a tree, you are supposed to tell if it is a complete binary tree. Input Specification: Each in ...

  5. 1110 Complete Binary Tree (25 分)

    Given a tree, you are supposed to tell if it is a complete binary tree. Input Specification: Each in ...

  6. PAT (Advanced Level) 1110. Complete Binary Tree (25)

    判断一棵二叉树是否完全二叉树. #include<cstdio> #include<cstring> #include<cmath> #include<vec ...

  7. PAT甲题题解-1110. Complete Binary Tree (25)-(判断是否为完全二叉树)

    题意:判断一个节点为n的二叉树是否为完全二叉树.Yes输出完全二叉树的最后一个节点,No输出根节点. 建树,然后分别将该树与节点树为n的二叉树相比较,统计对应的节点个数,如果为n,则为完全二叉树,否则 ...

  8. 【PAT甲级】1110 Complete Binary Tree (25分)

    题意: 输入一个正整数N(<=20),代表结点个数(0~N-1),接着输入N行每行包括每个结点的左右子结点,'-'表示无该子结点,输出是否是一颗完全二叉树,是的话输出最后一个子结点否则输出根节点 ...

  9. 1110 Complete Binary Tree

    1110 Complete Binary Tree (25)(25 分) Given a tree, you are supposed to tell if it is a complete bina ...

随机推荐

  1. Unity Reflection Probe使用入门

    贴官方API的说法: 反射探头: 一个反射探头很像一个相机,捕获了周围所有方向的球形视图.然后将捕获的图像存储为Cubemap,可由具有反射材料的对象使用.在给定场景中可以使用多个反射探测器,可以将对 ...

  2. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-search

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  3. netty权威指南学习笔记一——NIO入门(2)伪异步IO

    在上一节我们介绍了四种IO相关编程的各个特点,并通过代码进行复习了传统的网络编程代码,伪异步主要是引用了线程池,对BIO中服务端进行了相应的改造优化,线程池的引入,使得我们在应对大量客户端请求的时候不 ...

  4. 指令——ls

    Liunx基础命令 一.Liunx系统下的一般命令格式. 命令——实际上就是在Liunx终端中,在命令行中输入的内容. Liunx中一个命令的完整格式为: #指令主体(空格) [选项](空格) [操作 ...

  5. PyTorch自动微分基本原理

    序言:在训练一个神经网络时,梯度的计算是一个关键的步骤,它为神经网络的优化提供了关键数据.但是在面临复杂神经网络的时候导数的计算就成为一个难题,要求人们解出复杂.高维的方程是不现实的.这就是自动微分出 ...

  6. java核心-多线程(1)-知识大纲

    Thread,整理一份多线程知识大纲,大写意 1.概念介绍 线程 进程 并发 2.基础知识介绍 Java线程类 Thread 静态方法&实例方法 Runnable Callable Futur ...

  7. [转载]SQL Server 数据库定时自动备份

    推荐使用SQLserver自带的SSMS工具创建维护计划来实现数据库定时自动备份 “维护计划”是在SSMS的对象资源管理中“管理”节点下面.使用维护计划可以通过可视化的操作,只点点鼠标就可以创建数据库 ...

  8. Tunning spark

    Data Serialization 对spark程序来说,可能会产生的瓶颈包括:cpu,网络带宽,内存 在任何分布式应用中数据序列化都非常重要,数据序列化带来的作用是什么?第一减少内存占用,第二减小 ...

  9. 细说 OLAP 与 OLTP

    OLAP (Online analytical processing)[联机分析处理] 起源 数据库概念最初源于1962年Kenneth Iverson发表的名为"A Programming ...

  10. Ctrl + c 强制退出

    linux 使用cat 命令进入一个很大的文件,一直在不停地显示内容,让它停止的方法,可以用Ctrl + c 强制退出